<!-- 博客 - 页面布局 > 上中下 -->



<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=dark>
<!-- 博客 - 导航栏上方 -->


<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/blog/img/fluid.png">
  <link rel="icon" href="/blog/img/icon/dw.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="Memory">
  <meta name="keywords" content="">

  
    <meta name="description" content="🍝 站在巨人的肩膀上，从优秀案例中汲取灵感与智慧">
<meta property="og:type" content="article">
<meta property="og:title" content="卓越之旅：在优秀案例中精进，编织技术梦想">
<meta property="og:url" content="https://test.atomgit.net/blog/2024/07/12/%E5%8D%93%E8%B6%8A%E4%B9%8B%E6%97%85%EF%BC%9A%E5%9C%A8%E4%BC%98%E7%A7%80%E6%A1%88%E4%BE%8B%E4%B8%AD%E7%B2%BE%E8%BF%9B%EF%BC%8C%E7%BC%96%E7%BB%87%E6%8A%80%E6%9C%AF%E6%A2%A6%E6%83%B3/index.html">
<meta property="og:site_name" content="Memory&#39;s blog">
<meta property="og:description" content="🍝 站在巨人的肩膀上，从优秀案例中汲取灵感与智慧">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://test.atomgit.net/blog/img/artical/girl20240821.jpg">
<meta property="article:published_time" content="2024-07-12T02:36:11.000Z">
<meta property="article:modified_time" content="2025-11-07T11:51:11.000Z">
<meta property="article:author" content="Memory">
<meta property="article:tag" content="项目">
<meta property="article:tag" content="Vue">
<meta property="article:tag" content="毕设">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://test.atomgit.net/blog/img/artical/girl20240821.jpg">
  
  
  
  <title>卓越之旅：在优秀案例中精进，编织技术梦想 - Memory&#39;s blog</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/blog/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/blog/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/blog/css/highlight-dark.css" />
  



  
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"test.atomgit.net","root":"/blog/","version":"1.9.4","typing":{"enable":true,"typeSpeed":100,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":false,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":true,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"appId":"T1hUHH9Ks1ggG9DBE3HgUPpV-gzGzoHsz","appKey":"XFkgzzvzNo3J3uNCbBiSOFKc","server_url":"https://t1huhh9k.lc-cn-n1-shared.com","path":"window.location.pathname","ignore_local":false}},"search_path":"/blog/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/blog/js/utils.js" ></script>
  <script  src="/blog/js/color-schema.js" ></script>
  

  

  

  

  

  

  

  



  
<meta name="generator" content="Hexo 5.4.2"></head>

<body>
  

  <header>
    <!-- 博客 - 导航栏上方 -->


<div class="header-inner" style="height: 100vh">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/blog/">
      <strong>Memory&#39;s blog</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/archives/">
                <i class="iconfont icon-archive-fill"></i>
                <span>归档</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/categories/">
                <i class="iconfont icon-category-fill"></i>
                <span>分类</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/tags/">
                <i class="iconfont icon-tags-fill"></i>
                <span>标签</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/about/">
                <i class="iconfont icon-user-fill"></i>
                <span>关于</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/links/">
                <i class="iconfont icon-link-fill"></i>
                <span>友链</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/playlist/">
                <i class="iconfont icon-music"></i>
                <span>音乐</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/Memos/">
                <i class="iconfont icon-comment "></i>
                <span>说说</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/App/">
                <i class="iconfont icon-mobile"></i>
                <span>咫尺</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" target="_self" href="javascript:;" role="button"
                 data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-books"></i>
                <span>青简</span>
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="http://47.93.135.62:5230/explore">
                    <i class="iconfont icon-images"></i>
                    <span>碎念微光</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/blog/New/">
                    <i class="iconfont icon-bug"></i>
                    <span>匠册详析</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/blog/New/">
                    <i class="iconfont icon-xbox-fill"></i>
                    <span>窗景新编</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/blog/New/">
                    <i class="iconfont icon-steam"></i>
                    <span>戏码幕后</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/blog/New/">
                    <i class="iconfont icon-map"></i>
                    <span>他山随拾</span>
                  </a>
                
              </div>
            </li>
          
        
        
            <li class="nav-item" id="search-btn">
                <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalNotice" aria-label="Search">
                    <i class="iconfont icon-book"></i>
                    <span>公告</span>
                </a>
            </li>
            
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>
 
<div id="banner" class="banner" parallax=true
     style="background: url('/blog/img/artical/girl20240821.jpg') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">

    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">

        <div class="h2">
          
            <span id="subtitle" data-typed-text="卓越之旅：在优秀案例中精进，编织技术梦想"></span>
          
        </div>


        
          <!-- 文章页面 - 顶部信息 -->

<div class="mt-3">
  
  <span class="post-meta mr-2">
    <i class="iconfont icon-author" aria-hidden="true"></i>
    Memory
  </span>
   
  <span class="post-meta">
    <i class="iconfont icon-date-fill" aria-hidden="true"></i>
    <time datetime="2024-07-12 10:36" pubdate>
      2024年7月12日 上午
    </time>
  </span>
  
</div>

<div class="mt-1">
  
  <span class="post-meta mr-2">
    <i class="iconfont icon-chart"></i>
     182k 字 
  </span>
   
  <span class="post-meta mr-2">
    <i class="iconfont icon-clock-fill"></i>
       457 分钟 
  </span>
     
  <span
    id="leancloud-page-views-container"
    class="post-meta"
    style="display: none"
  >
    <i class="iconfont icon-eye" aria-hidden="true"></i>
    <span id="leancloud-page-views"></span> 次
  </span>

    
</div>


        

        <!-- 添加网站运行时间 -->
        <div class="footer-content" style="background-color: transparent;">
          <div>
            <span id="timeDate"></span>
            <span id="times"></span>
            <script>
            var now = new Date();
            function createtime(){
                var grt= new Date("03/07/2023 00:00:00");//此处修改你的建站时间或者网站上线时间
                now.setTime(now.getTime()+250);
                days = (now - grt ) / 1000 / 60 / 60 / 24;
                dnum = Math.floor(days);
                hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum);
                hnum = Math.floor(hours);
                if(String(hnum).length ==1 ){
                    hnum = "0" + hnum;
                }
                minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);
                mnum = Math.floor(minutes);
                if(String(mnum).length ==1 ){
                          mnum = "0" + mnum;
                }
                seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
                snum = Math.round(seconds);
                if(String(snum).length ==1 ){
                          snum = "0" + snum;
                }
                document.getElementById("timeDate").innerHTML = "🚀 &nbsp"+dnum+"&nbsp天";  //此次自定义显示内容
                document.getElementById("times").innerHTML = hnum + "&nbsp小时&nbsp" + mnum + "&nbsp分&nbsp" + snum + "&nbsp秒";
            }  

            if (!window.location.href.includes('/20')) {  
            setInterval("createtime()", 250);  // 只有当URL不包含'specific-page'时，才调用createtime  
            }//此次自定义显示内容
            </script>
          </div>
        </div>

      </div>
      
        <div class="scroll-down-bar">
          <i class="iconfont icon-arrowdown"></i>
        </div>
      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      <!-- 文章页  -->


<div class="container-fluid nopadding-x">

  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar category-bar" style="margin-right: -1rem">
    <!-- 文章页面 - 左边栏所属分类 -->
  

<!-- 文章页 - 文章分类 -->





<div class="category-list">
  
  
    
    
    
    <div class="category row nomargin-x">
      <a class="category-item 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="代码锋芒"
        id="heading-843238cb7c4b39b52e95311733ff6da6" role="tab" data-toggle="collapse" href="#collapse-843238cb7c4b39b52e95311733ff6da6"
        aria-expanded="true"
      >
        代码锋芒
        <span class="list-group-count">(31)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-843238cb7c4b39b52e95311733ff6da6"
           role="tabpanel" aria-labelledby="heading-843238cb7c4b39b52e95311733ff6da6">
        
        
          
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2023/03/19/MySQL%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE/" title="MySQL安装配置"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">MySQL安装配置</span>
        </a>
      
    
      
      
        <a href="/blog/2023/03/22/MySQL%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%85%A5%E5%9C%9F/" title="MySQL从入门到入土"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">MySQL从入门到入土</span>
        </a>
      
    
      
      
        <a href="/blog/2023/04/09/Java%E6%B3%9B%E5%9E%8B%E7%9A%84%E7%90%86%E8%A7%A3/" title="Java泛型：赋予灵活性的利器"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">Java泛型：赋予灵活性的利器</span>
        </a>
      
    
      
      
        <a href="/blog/2023/05/21/%E6%8E%A2%E7%B4%A2%20Python%20%E7%88%AC%E8%99%AB%E7%9A%84%E6%97%A0%E9%99%90%E5%8F%AF%E8%83%BD%E6%80%A7%EF%BC%9A%E5%9F%BA%E7%A1%80%E4%B8%8E%E5%BA%94%E7%94%A8/" title="探索Python爬虫的无限可能性：基础与应用"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">探索Python爬虫的无限可能性：基础与应用</span>
        </a>
      
    
      
      
        <a href="/blog/2023/06/03/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E7%9A%84%20JavaWeb%20%E4%B9%8B%E6%97%85/" title="从零开始的 JavaWeb 之旅"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">从零开始的 JavaWeb 之旅</span>
        </a>
      
    
      
      
        <a href="/blog/2023/06/10/%E6%95%B0%E6%8D%AE%E5%BA%93-%E5%AE%8C%E6%95%B4%E6%80%A7%E7%BA%A6%E6%9D%9F/" title="数据库-完整性约束"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">数据库-完整性约束</span>
        </a>
      
    
      
      
        <a href="/blog/2023/06/24/%E4%BD%BF%E7%94%A8%20JSP%20%E6%9E%84%E5%BB%BA%20JavaWeb%20%E9%A1%B9%E7%9B%AE-%E4%BB%A5%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%A7%E4%BD%9C%E4%B8%9A%E4%B8%BA%E4%BE%8B/" title="使用JSP构建JavaWeb项目--以数据库大作业为例"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">使用JSP构建JavaWeb项目--以数据库大作业为例</span>
        </a>
      
    
      
      
        <a href="/blog/2023/07/06/%E6%89%93%E9%80%A0%E6%B5%81%E7%95%85%E7%BC%96%E7%A0%81%E4%B9%8B%E6%97%85%EF%BC%9AIntelliJ%20IDEA%20%E7%9A%84%E9%AB%98%E6%95%88%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7%E4%B8%8E%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B%E4%BC%98%E5%8C%96/" title="打造流畅编码之旅：IntelliJ IDEA 的高效使用技巧与工作流程优化"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">打造流畅编码之旅：IntelliJ IDEA 的高效使用技巧与工作流程优化</span>
        </a>
      
    
      
      
        <a href="/blog/2023/07/06/%E5%87%A4%E5%87%B0%E6%B6%85%E6%A7%83%EF%BC%9ASpring%20Boot%20%E5%BC%80%E5%8F%91%E4%B9%8B%E8%B7%AF%E4%B8%8A%E7%9A%84%E5%9D%8E%E5%9D%B7%E4%B8%8E%E6%88%90%E9%95%BF/" title="凤凰涅槃：Spring Boot 开发之路上的坎坷与成长"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">凤凰涅槃：Spring Boot 开发之路上的坎坷与成长</span>
        </a>
      
    
      
      
        <a href="/blog/2023/07/11/%E4%BB%8EIP%E5%88%B0Ping%E5%91%BD%E4%BB%A4%EF%BC%9A%E4%BA%86%E8%A7%A3%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%BF%9E%E6%8E%A5%E7%9A%84%E5%9F%BA%E7%A1%80/" title="从IP到Ping命令：了解计算机网络连接的基础"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">从IP到Ping命令：了解计算机网络连接的基础</span>
        </a>
      
    
      
      
        <a href="/blog/categories/%E4%BB%A3%E7%A0%81%E9%94%8B%E8%8A%92/" class="list-group-item list-group-item-action">
          <span class="category-post">More...</span>
        </a>
        
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="职路星火"
        id="heading-59c550454d1ecf67a2ead26a1c46d14b" role="tab" data-toggle="collapse" href="#collapse-59c550454d1ecf67a2ead26a1c46d14b"
        aria-expanded="false"
      >
        职路星火
        <span class="list-group-count">(2)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-59c550454d1ecf67a2ead26a1c46d14b"
           role="tabpanel" aria-labelledby="heading-59c550454d1ecf67a2ead26a1c46d14b">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2024/03/07/%E7%A0%BA%E5%89%91%E5%87%BA%E9%9E%98%EF%BC%9A%E6%88%91%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%B1%82%E8%81%8C%E4%B9%8B%E6%97%85/" title="砺剑出鞘：我的软件工程师求职之旅"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">砺剑出鞘：我的软件工程师求职之旅</span>
        </a>
      
    
      
      
        <a href="/blog/2024/04/16/%E6%8B%A8%E4%BA%91%E8%A7%81%E6%97%A5%EF%BC%9A%E8%81%8C%E5%9C%BA%E7%94%9F%E6%B4%BB%E7%9A%84%E7%82%B9%E6%BB%B4%E8%AE%B0%E5%BD%95/" title="拨云见日：职场生活的点滴记录"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">拨云见日：职场生活的点滴记录</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="部署之道"
        id="heading-36acf247b1a64f4bbe423776a392cfde" role="tab" data-toggle="collapse" href="#collapse-36acf247b1a64f4bbe423776a392cfde"
        aria-expanded="false"
      >
        部署之道
        <span class="list-group-count">(5)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-36acf247b1a64f4bbe423776a392cfde"
           role="tabpanel" aria-labelledby="heading-36acf247b1a64f4bbe423776a392cfde">
        
        
          
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2023/06/22/Nginx%20%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97%EF%BC%9A%E7%90%86%E8%A7%A3%E3%80%81%E9%85%8D%E7%BD%AE%E5%92%8C%E4%BC%98%E5%8C%96/" title="Nginx 入门指南：理解、配置和优化"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">Nginx 入门指南：理解、配置和优化</span>
        </a>
      
    
      
      
        <a href="/blog/2023/07/11/Docker%20%E5%85%A5%E9%97%A8%E4%B8%8E%E5%AE%9E%E8%B7%B5%EF%BC%9A%E5%BF%AB%E9%80%9F%E6%89%93%E9%80%A0%E9%AB%98%E6%95%88%E7%BD%91%E7%AB%99%E9%83%A8%E7%BD%B2%E7%8E%AF%E5%A2%83/" title="Docker入门与实践：快速打造高效网站部署环境"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">Docker入门与实践：快速打造高效网站部署环境</span>
        </a>
      
    
      
      
        <a href="/blog/2023/08/17/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%20API%20%E7%BD%91%E5%85%B3%EF%BC%9A%E5%8E%9F%E7%90%86%E3%80%81%E5%8A%9F%E8%83%BD%E5%92%8C%E7%94%A8%E9%80%94/" title="深入理解 API 网关：原理、功能和用途"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">深入理解 API 网关：原理、功能和用途</span>
        </a>
      
    
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="职路星火"
        id="heading-59c550454d1ecf67a2ead26a1c46d14b" role="tab" data-toggle="collapse" href="#collapse-59c550454d1ecf67a2ead26a1c46d14b"
        aria-expanded="false"
      >
        职路星火
        <span class="list-group-count">(2)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-59c550454d1ecf67a2ead26a1c46d14b"
           role="tabpanel" aria-labelledby="heading-59c550454d1ecf67a2ead26a1c46d14b">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2024/12/16/%E6%BC%AB%E6%BC%AB%E5%BE%81%E9%80%94%EF%BC%9A%E7%AD%91%E6%A2%A6%E4%BA%8E%E8%81%8C%E5%9C%BA%E9%A3%8E%E9%9B%A8%EF%BC%8C%E5%90%9F%E5%92%8F%E4%BA%8E%E6%97%A5%E5%B8%B8%E8%AF%97%E6%84%8F/" title="漫漫征途：筑梦于职场风雨，吟咏于日常诗意"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">漫漫征途：筑梦于职场风雨，吟咏于日常诗意</span>
        </a>
      
    
      
      
        <a href="/blog/2025/10/23/%E4%BF%9D%E9%A9%BE%E6%8A%A4%E8%88%AA%E2%80%94%E2%80%94%E5%90%8E%E5%8F%B0%E8%BF%90%E7%BB%B4%E8%A7%86%E8%A7%92%E4%B8%8B%E7%9A%84%E9%AB%98%E9%80%9F%E5%85%AC%E8%B7%AF%E2%80%9C%E7%94%9F%E5%91%BD%E7%BA%BF%E2%80%9D/" title="保驾护航——后台运维视角下的高速公路“生命线”"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">保驾护航——后台运维视角下的高速公路“生命线”</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
        
      </div>
    </div>
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="项目志录"
        id="heading-005e56101bc2a873707cb4461a70ded8" role="tab" data-toggle="collapse" href="#collapse-005e56101bc2a873707cb4461a70ded8"
        aria-expanded="false"
      >
        项目志录
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-005e56101bc2a873707cb4461a70ded8"
           role="tabpanel" aria-labelledby="heading-005e56101bc2a873707cb4461a70ded8">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2023/07/30/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%EF%BC%9A%E8%B8%A9%E5%9D%91%E6%8C%87%E5%8D%97%E4%B8%8E%E6%8A%80%E5%B7%A7%E6%80%BB%E7%BB%93/" title="小程序开发经验分享：踩坑指南与技巧总结"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">小程序开发经验分享：踩坑指南与技巧总结</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
        
      </div>
    </div>
  
</div>

  </aside>


    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">卓越之旅：在优秀案例中精进，编织技术梦想</h1>
            
              <p class="note note-success">
                
                  
                    本文最后更新于：1 个月前
                  
                
              </p>
            
            
              <div class="markdown-body">
                
                <h1 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h1><blockquote>
<p>2024 年 7 月 12 日</p>
</blockquote>
<p>为什么会突然想到写这样一篇博客呢？我简单反省过这半年来的学习规划，确实很长时间没有更新过专精编程技术的博客了。</p>
<p>在今年这个最关键的时间节点，我很清楚自己最需要做什么。</p>
<p>在今年上半年有过的唯一一段工作经历，让我越发清醒地意识到：在持续备战秋招的忙碌生活中，我必须要找到自己真正喜欢并愿意长期付之以时间的爱好。</p>
<p>最近很喜欢研究象棋，也在尝试了解学习视频剪辑的艺术，更多的是通过读书，写作来记录生活，陶冶情操。</p>
<p>那段工作经历让我真正意识到，工作只是生存的一部分，上班之余的时间才算是真正的生活。</p>
<p>所以我更希望能够在工作之余的闲暇时间，做点什么来充实自己的业余生活。</p>
<p>我发觉到长期处于烦闷无聊的工作中，我对编程学习的兴趣在逐渐消退了，我需要重新汲取外部优质资源。</p>
<p><strong>站在巨人的肩膀上，开启我的编程精进之路。</strong></p>
<h1 id="项目"><a href="#项目" class="headerlink" title="项目"></a>项目</h1><h2 id="仿网易云音乐"><a href="#仿网易云音乐" class="headerlink" title="仿网易云音乐"></a>仿网易云音乐</h2><p>🍖 推荐阅读：</p>
<p><a target="_blank" rel="noopener" href="https://music.163.com/#/discover">网易云音乐 (163.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://nodejs.org/zh-cn/learn/getting-started/nodejs-the-difference-between-development-and-production">Node.js — Node.js, the difference between development and production (nodejs.org)</a></p>
<h3 id="项目启动"><a href="#项目启动" class="headerlink" title="项目启动"></a>项目启动</h3><blockquote>
<p>2024 年 7 月 12 日</p>
</blockquote>
<p>前端项目跑起来：</p>
<p>当在命令行中遇到 <code>&#39;vue-cli-service&#39; 不是内部或外部命令，也不是可运行的程序或批处理文件</code> 这个错误时，这通常意味着你的系统中没有正确安装 Vue CLI 或者其可执行文件 <code>vue-cli-service</code> 没有被添加到系统的 PATH 环境变量中。以下是一些解决这个问题的步骤：</p>
<p><img src="http://blog.memory-life.xyz/image-20240712170550777.png" alt="image-20240712170550777"></p>
<ol>
<li>确认 Vue CLI 是否已安装</li>
</ol>
<p>首先，你需要确认 Vue CLI 是否已经安装在你的机器上。打开命令行工具，输入以下命令来检查 Vue CLI 是否安装以及其版本：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>vue --version<br></code></pre></td></tr></table></figure>

<p>如果系统提示 <code>vue</code> 命令找不到，那么你需要安装 Vue CLI。</p>
<ol start="2">
<li>安装 Vue CLI</li>
</ol>
<p>如果 Vue CLI 没有安装，你可以通过 npm（Node.js 的包管理器）来安装它。首先，确保你已经安装了 Node.js 和 npm。然后，在命令行中运行以下命令来全局安装 Vue CLI：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>npm install -g @vue/cli<br></code></pre></td></tr></table></figure>

<p>或者使用 yarn（如果你更倾向于使用 yarn）：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>yarn global add @vue/cli<br></code></pre></td></tr></table></figure>

<ol start="3">
<li>尝试再次运行你的项目</li>
</ol>
<p>在完成上述步骤后，回到你的 Vue 项目目录，并尝试再次运行：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>vue-cli-service serve<br></code></pre></td></tr></table></figure>

<p>4.要是还是不行，就直接执行：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install<br></code></pre></td></tr></table></figure>

<p>本项目后端依赖于这个开源的网易云音乐 API 接口项目，请自行下载并运行：<a target="_blank" rel="noopener" href="https://github.com/xunlu129/NeteaseCloudMusicApi"><strong>NeteaseCloudMusicApi</strong></a></p>
<h3 id="后端启动"><a href="#后端启动" class="headerlink" title="后端启动"></a>后端启动</h3><blockquote>
<p>2024 年 7 月 21 日</p>
</blockquote>
<p>本项目后端依赖于这个开源的网易云音乐 API 接口项目，请自行下载并运行：</p>
<p><a target="_blank" rel="noopener" href="https://github.com/xunlu129/NeteaseCloudMusicApi">NeteaseCloudMusicApi</a></p>
<p><img src="http://blog.memory-life.xyz/image-20240721134317108.png" alt="image-20240721134317108"></p>
<p>这个错误提示 <code>CERT_HAS_EXPIRED</code> 表示你尝试连接到 npm 注册表时使用的 SSL 证书已经过期。这通常是因为你的 npm 客户端配置使用了过时的注册表 URL 或者你的系统日期和时间设置不正确。以下是一些解决这个问题的步骤：</p>
<ol>
<li><p><strong>检查系统日期和时间</strong>：<br>确保你的计算机的系统日期和时间设置是正确的。错误的日期和时间设置可能导致 SSL 证书验证失败。</p>
</li>
<li><p><strong>检查 npm 配置</strong>：<br>运行 <code>npm config list</code> 来查看当前的 npm 配置，特别是 <code>registry</code> 的值。它应该指向 <code>https://registry.npmjs.org/</code>。如果指向的是 http 而非 https，或者是一个其他非官方镜像，请考虑修改它。</p>
<p>你可以使用以下命令来设置 npm 的默认注册表地址：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>npm config <span class="hljs-built_in">set</span> registry https://registry.npmjs.org/<br></code></pre></td></tr></table></figure></li>
<li><p><strong>清除 npm 缓存</strong>：<br>有时候清除 npm 缓存可以解决奇怪的安装问题。你可以使用以下命令来清除缓存：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>npm cache clean --force<br></code></pre></td></tr></table></figure></li>
<li><p><strong>检查网络设置</strong>：<br>如果你在公司或学校网络环境中，可能存在网络代理或防火墙设置阻止了 https 连接的正确验证。你可以尝试暂时关闭这些设置或使用其他网络环境来查看问题是否仍然存在。</p>
</li>
<li><p><strong>更新 npm 和 Node.js</strong>：<br>确保你的 npm 和 Node.js 都是最新版本。旧版本的 npm 可能不支持 TLS 1.2 或更高版本。你可以通过运行以下命令来更新 npm：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>npm install -g npm<br></code></pre></td></tr></table></figure>

<p>如果需要更新 Node.js，你可以从 <a target="_blank" rel="noopener" href="https://nodejs.org/">Node.js 官网</a> 下载最新版本。</p>
</li>
<li><p><strong>检查代理和 SSL 证书</strong>：<br>如果你在使用代理或 SSL 证书，请确保它们是最新的，并且正确配置在你的系统上。</p>
</li>
<li><p><strong>尝试使用 VPN</strong>：<br>有时网络问题可能由地理位置或 ISP 限制引起。尝试使用 VPN 连接到其他网络，看看是否可以解决问题。</p>
</li>
</ol>
<p>再次执行，又出现这个问题：</p>
<p><img src="http://blog.memory-life.xyz/image-20240721135004787.png" alt="image-2024072113500477"></p>
<figure class="highlight coffeescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs coffeescript">`<span class="language-javascript"><span class="hljs-variable constant_">ERR_SOCKET_TIMEOUT</span></span>` 错误表明 <span class="hljs-built_in">npm</span> 在尝试从 <span class="hljs-built_in">npm</span> 注册表下载包时，由于网络问题导致连接超时。这通常与网络连接质量、代理设置、防火墙规则或 <span class="hljs-built_in">npm</span> 服务器的响应速度有关。以下是一些解决这个问题的步骤：<br></code></pre></td></tr></table></figure>

<p>如果你在中国大陆或其他地区，使用 npm 官方注册表可能受到网络延迟或限制的影响。你可以考虑使用 npm 镜像，如淘宝的 npm 镜像（cnpm）：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install -g cnpm --registry=https://registry.npm.taobao.org<br><span class="hljs-comment"># 然后使用 cnpm 代替 npm</span><br>cnpm install<br></code></pre></td></tr></table></figure>

<p>我尝试安装 cnpm，结果有报错：</p>
<p><img src="http://blog.memory-life.xyz/image-20240721135453761.png" alt="image-20240721135453761"></p>
<p>遇到 <code>CERT_HAS_EXPIRED</code> 错误通常意味着你尝试连接的服务器使用的 SSL 证书已经过期。然而，在这个情况下，你尝试访问的是淘宝的 npm 镜像（<code>https://registry.npm.taobao.org</code>），这是一个被广泛使用的、应该保持证书有效的镜像。</p>
<p>这个问题可能由以下几个原因引起：</p>
<ol>
<li><strong>系统时间设置错误</strong>：检查你的计算机的系统时间是否正确。错误的系统时间会导致 SSL 证书验证失败，因为证书的有效期是基于时间的。</li>
<li><strong>网络中间人攻击（MITM）</strong>：虽然不太可能，但你的网络可能被配置为拦截 SSL/TLS 连接，并使用自己的证书。这通常发生在公司网络或受限制的网络环境中。</li>
<li><strong>本地 SSL/TLS 证书存储问题</strong>：你的系统可能无法正确访问或验证 SSL 证书链。</li>
<li><strong>npm 配置问题</strong>：尽管你已经检查了 <code>proxy</code> 配置，但还有其他与 SSL 相关的配置可能需要检查，如 <code>strict-ssl</code>。</li>
</ol>
<p>为了解决这个问题，你可以尝试以下步骤：</p>
<ul>
<li><p><strong>检查系统时间</strong>：确保你的系统时间是准确的。</p>
</li>
<li><p><strong>使用命令行工具检查 SSL 证书</strong>：你可以使用如 <code>openssl</code> 的命令行工具来检查 <code>https://registry.npm.taobao.org</code> 的 SSL 证书是否有效。例如：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>openssl s_client -connect registry.npm.taobao.org:443<br></code></pre></td></tr></table></figure>

<p>查看输出中的证书信息，特别是有效期部分。</p>
</li>
<li><p><strong>暂时禁用 SSL 验证</strong>（仅作为测试，不推荐长期使用）：<br>你可以通过设置 <code>strict-ssl</code> 为 <code>false</code> 来暂时禁用 npm 的 SSL 验证。但请注意，这会使你的连接容易受到中间人攻击。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm config <span class="hljs-built_in">set</span> strict-ssl <span class="hljs-literal">false</span><br>npm install -g cnpm --registry=https://registry.npm.taobao.org<br><span class="hljs-comment"># 记得之后将其设置回 true</span><br>npm config <span class="hljs-built_in">set</span> strict-ssl <span class="hljs-literal">true</span><br></code></pre></td></tr></table></figure></li>
<li><p><strong>清理 npm 缓存</strong>：<br>虽然这不太可能是证书问题的直接解决方案，但清理缓存有时可以解决一些奇怪的问题。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>npm cache clean --force<br></code></pre></td></tr></table></figure></li>
<li><p><strong>使用其他网络</strong>：尝试连接到其他网络（如家庭网络或移动热点），以查看问题是否仍然存在。</p>
</li>
<li><p><strong>更新 npm 和 Node.js</strong>：确保你的 npm 和 Node.js 都是最新版本。</p>
</li>
<li><p><strong>联系淘宝 npm 镜像的支持</strong>：如果以上步骤都不能解决问题，可能需要联系淘宝 npm 镜像的支持团队，询问他们是否有关于证书过期的已知问题。</p>
</li>
</ul>
<p>请注意，禁用 SSL 验证（<code>strict-ssl=false</code>）应该只作为最后的手段，并且仅在你完全信任你的网络环境时使用。在生产环境中，始终应该保持 SSL 验证启用。</p>
<p>执行成功！</p>
<p><img src="http://blog.memory-life.xyz/image-20240721140507470.png" alt="image-20240721140507470"></p>
<p>执行以下命令，启动后台：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">node app.js<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20240721142332268.png" alt="image-20240721142332268"></p>
<p>启动前台页面：</p>
<p><img src="http://blog.memory-life.xyz/image-20240721142357687.png" alt="image-20240721142357687"></p>
<p>访问，项目效果如下：</p>
<p><img src="http://blog.memory-life.xyz/image-20240721142531038.png" alt="image-20240721142531038"></p>
<p><img src="http://blog.memory-life.xyz/image-20240721142503392.png" alt="image-20240721142503392"></p>
<p><img src="http://blog.memory-life.xyz/image-20240721142511135.png" alt="image-20240721142511135"></p>
<h2 id="仿-B-站项目"><a href="#仿-B-站项目" class="headerlink" title="仿 B 站项目"></a>仿 B 站项目</h2><h3 id="项目启动-1"><a href="#项目启动-1" class="headerlink" title="项目启动"></a>项目启动</h3><blockquote>
<p>2024 年 7 月 21 日</p>
</blockquote>
<p>了解整体代码结构，熟悉数据库库表和字段，修改数据库配置。</p>
<p>暂时不做 Elasticsearch 和 阿里云 OSS 对象存储的配置。</p>
<p>xxxxxxxxxx <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>com.memory.api</groupId>        <artifactId>memory-api</artifactId>        <version>0.0.1-SNAPSHOT</version>        <relativePath>../pom.xml</relativePath>    </parent>​    <groupId>com.memory.client</groupId>    <artifactId>memory-client</artifactId>    <version>0.0.1-SNAPSHOT</version>​    <dependencies>        <dependency>            <groupId>com.memory.common</groupId>            <artifactId>memory-common</artifactId>            <version>0.0.1-SNAPSHOT</version>        </dependency>        <dependency>            <groupId>com.belerweb</groupId>            <artifactId>pinyin4j</artifactId>            <version>2.5.1</version> <!-- 使用时检查是否有更新的版本 -->        </dependency>        <dependency>            <groupId>com.memory</groupId>            <artifactId>memory-client-spring-boot-starter</artifactId>            <version>0.0.1</version>        </dependency>    </dependencies>​    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>                <executions>                    <execution>                        <id>repackage</id>                        <goals>                            <goal>repackage</goal>                        </goals>                    </execution>                </executions>            </plugin>        </plugins>    </build>​</project>​xml</p>
<p>👆 这是 Category 表没有默认主键，添加上即可：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Category</span> &#123;<br>    <span class="hljs-meta">@TableId(type = IdType.AUTO)</span><br>    <span class="hljs-keyword">private</span> String mcId;<br>    <span class="hljs-keyword">private</span> String scId;<br>    <span class="hljs-keyword">private</span> String mcName;<br>    <span class="hljs-keyword">private</span> String scName;<br>    <span class="hljs-keyword">private</span> String descr;<br>    <span class="hljs-keyword">private</span> String rcmTag;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20240721192005290.png" alt="image-20240721192005290"></p>
<p>ES 配置问题，直接注销掉 ElasticsearchConfig 配置，以及 ESUtils 自动注入。</p>
<p>OSS 配置问题，同样的，只不过引用的地方比较多，暂时都注释掉相关代码。</p>
<p>当然，可以简单配置自己本地的 Elasticsearch 和 阿里云 OSS ，现在为了简便就直接注释掉部分代码，先把项目跑起来再说。</p>
<p>后端直接启动 BackendApplication 即可。</p>
<p>前端更容易了，执行 <code>npm install</code> 安装依赖无误后，直接执行 <code>vue-cli-service serve</code> 启动项目：</p>
<p><img src="http://blog.memory-life.xyz/image-20240721193910677.png" alt="image-20240721193910677"></p>
<p>至此，项目启动成功，效果如下：</p>
<p><img src="http://blog.memory-life.xyz/image-20240721193959515.png" alt="image-20240721193959515"></p>
<p><img src="http://blog.memory-life.xyz/image-20240721194005561.png" alt="image-20240721194005561"></p>
<h3 id="配置更改"><a href="#配置更改" class="headerlink" title="配置更改"></a>配置更改</h3><blockquote>
<p>2024 年 7 月 27 日</p>
</blockquote>
<p>这天一直在抽空学习 Vue 基础，今晚也总算抽出时间来观摩观摩这个项目。</p>
<p>修改了 Redis 和 Elasticsearch 配置：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">spring:</span><br>  <span class="hljs-attr">redis:</span><br>    <span class="hljs-attr">database:</span> <span class="hljs-number">4</span><br>    <span class="hljs-attr">host:</span> <span class="hljs-string">localhost</span><br>    <span class="hljs-attr">port:</span> <span class="hljs-number">6379</span><br>    <span class="hljs-attr">password:</span> <span class="hljs-string">Dw990831</span><br>    <span class="hljs-attr">jedis:</span><br>      <span class="hljs-attr">pool:</span><br>        <span class="hljs-attr">min-idle:</span> <span class="hljs-number">10</span><br>        <span class="hljs-attr">max-idle:</span> <span class="hljs-number">10</span><br>        <span class="hljs-attr">max-active:</span> <span class="hljs-number">100</span><br>        <span class="hljs-attr">max-wait:</span> <span class="hljs-number">-1</span><br>    <span class="hljs-attr">timeout:</span> <span class="hljs-number">5000</span><br></code></pre></td></tr></table></figure>

<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-comment"># Elasticsearch</span><br><span class="hljs-attr">elasticsearch:</span><br>  <span class="hljs-attr">host:</span> <span class="hljs-string">localhost</span><br>  <span class="hljs-attr">port:</span> <span class="hljs-number">9200</span><br>  <span class="hljs-attr">username:</span> <span class="hljs-string">root</span><br>  <span class="hljs-attr">password:</span> <span class="hljs-number">123456</span><br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20240727235753087.png" alt="image-20240727235753087"></p>
<p>这个问题是连接本地 Redis 客户端失败了：</p>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20240728000254042.png" alt="image-20240728000254042"></p>
<p>这样问题虽然没解决，但是起码注册流程跑通了，登陆还有问题，归根结底还是 Jedis 数据库连接至配置问题，这部分内容明天学习。</p>
<blockquote>
<p>2024 年 8 月 21 日</p>
</blockquote>
<p><img src="C:/Users/Lenovo/AppData/Roaming/Typora/typora-user-images/image-20240821233613716.png" alt="image-20240821233613716"></p>
<p>今天晚上回来分别把 Redis 和 Elasticsearch 在本地配置完善并启动后，成功实现了视频上传功能，视频已经能正确上传至阿里云存储桶中。</p>
<p>前后台用户注册登录也令人相当满意，视频审核也测试完成，就是上传视频的封面显示有些问题，而且目前不支持在线浏览视频。</p>
<p>待解决。</p>
<h3 id="在线聊天"><a href="#在线聊天" class="headerlink" title="在线聊天"></a>在线聊天</h3><blockquote>
<p>2024 年 10 月 4 日</p>
</blockquote>
<p>端口监听，连接管理，发送消息，接收消息，消息存储，消息状态（已读，未读）；</p>
<p>聊天列表，窗口状态（在线，离开）；</p>
<h2 id="实时通信"><a href="#实时通信" class="headerlink" title="实时通信"></a>实时通信</h2><blockquote>
<p>2025 年 2 月 28 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_34147283/article/details/143011903">IM 即时通讯的实现方式_即时聊天实现-CSDN 博客</a></p>
<blockquote>
<p>2024 年 10 月 4 日</p>
</blockquote>
<p>假期第四天，总算步入正轨了。</p>
<p>上午学习了仿 B 站项目的基于 Netty 的在线聊天功能，涉及到连接管理，消息管理，窗口管理等核心功能，对在线聊天实现有了更多新的想法。</p>
<p>下午会继续学习 WebSocket 实现实时通信，今天就要把这块儿内容搞定，最好写出 Demo 代码长期巩固记忆，日后在实践中运用。</p>
<blockquote>
<p>2024 年 10 月 5 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/haoyuegongzi/article/details/103001032">OkHttp 系列一、使用 OkHttp 进行网络请求的 4 个步骤-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/wei7a7a7a/article/details/131226019">OkhttpClient 的使用-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7192927482662617145?searchId=202410051153331920CB693867159E9C99">WebSocket 入门：简易聊天室大家好，我是前端西瓜哥，今天我们用 WebSocket 来实现一个简单的聊天室。 W - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/6844904014908227598">Java 项目中的 WebSocket 实现这种方式需要 tomcat 7.x，JEE7 的支持。 这种方式需要 spr - 掘金 (juejin.cn)</a></p>
<h3 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h3><p>服务端完整代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.memory.simplewebsocket.server;<br><br><span class="hljs-keyword">import</span> jakarta.websocket.*;<br><span class="hljs-keyword">import</span> jakarta.websocket.server.PathParam;<br><span class="hljs-keyword">import</span> jakarta.websocket.server.ServerEndpoint;<br><span class="hljs-keyword">import</span> org.slf4j.Logger;<br><span class="hljs-keyword">import</span> org.slf4j.LoggerFactory;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Component;<br><br><span class="hljs-keyword">import</span> java.io.IOException;<br><span class="hljs-keyword">import</span> java.util.HashMap;<br><span class="hljs-keyword">import</span> java.util.Map;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * ClassName: TomcatWebsocketServer</span><br><span class="hljs-comment"> * Package: com.memory.simplewebsocket.server</span><br><span class="hljs-comment"> * Description:</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Author</span> Memory</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Create</span> 2024/10/5 10:11</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Version</span> 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-meta">@Component</span><br><span class="hljs-meta">@ServerEndpoint(&quot;/chat/&#123;userId&#125;&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TomcatWebsocketServer</span> &#123;<br>    <span class="hljs-comment">// 管理连接</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Map&lt;Long, Session&gt; clients = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span>&lt;&gt;();<br>    <span class="hljs-comment">// 日志打印</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">Logger</span> <span class="hljs-variable">logger</span> <span class="hljs-operator">=</span> LoggerFactory.getLogger(ServerEndpoint.class);<br>    <span class="hljs-comment">// 用户</span><br>    <span class="hljs-keyword">private</span> Long userId;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 开启连接, 触发</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> session 会话</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> userId  用户</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@OnOpen</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onOpen</span><span class="hljs-params">(Session session, <span class="hljs-meta">@PathParam(&quot;userId&quot;)</span> Long userId)</span> &#123;<br>        <span class="hljs-built_in">this</span>.userId = userId;<br>        <span class="hljs-comment">// 存储用户和对应会话</span><br>        clients.put(userId, session);<br>        logger.info(String.format(<span class="hljs-string">&quot;用户 %d 已上线，新的连接 ------------------&gt; %s&quot;</span>, <span class="hljs-built_in">this</span>.userId, session.getId()));<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 收到消息, 触发</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> message 消息</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> session 会话</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@OnMessage</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onMessage</span><span class="hljs-params">(String message, Session session)</span> &#123;<br>        logger.info(String.format(<span class="hljs-string">&quot;收到来自 %d 的消息 ------------------&gt; %s&quot;</span>, userId, message));<br>        <span class="hljs-comment">// 向全体在线成员推送这条消息</span><br>        sendMessageFromOneToAll(message);<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 关闭连接, 触发</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> session 会话</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@OnClose</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onClose</span><span class="hljs-params">(Session session)</span> &#123;<br>        clients.remove(session);<br>        logger.info(String.format(<span class="hljs-string">&quot;连接关闭 ------------------&gt; %s&quot;</span>, session.getId()));<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 连接错误, 触发</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> session   会话</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> throwable 异常</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@OnError</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onError</span><span class="hljs-params">(Session session, Throwable throwable)</span> &#123;<br>        logger.info(String.format(<span class="hljs-string">&quot;连接错误 ------------------&gt; %s&quot;</span>, session.getId()));<br>        throwable.printStackTrace();<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 广播消息</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> message 消息</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">sendMessageFromOneToAll</span><span class="hljs-params">(String message)</span> &#123;<br>        clients.forEach((userId, session) -&gt; &#123;<br>            <span class="hljs-keyword">try</span> &#123;<br>                session.getBasicRemote().sendText(String.format(<span class="hljs-string">&quot;广播来自 %d 的消息 ------------------&gt; %s%n&quot;</span>, <span class="hljs-built_in">this</span>.userId, message));<br>            &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>                e.printStackTrace();<br>            &#125;<br>        &#125;);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h3><p>客户端完整代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.memory.simplewebsocket.listener;<br><br><span class="hljs-keyword">import</span> okhttp3.OkHttpClient;<br><span class="hljs-keyword">import</span> okhttp3.Request;<br><span class="hljs-keyword">import</span> okhttp3.WebSocket;<br><span class="hljs-keyword">import</span> okhttp3.WebSocketListener;<br><br><span class="hljs-keyword">import</span> java.util.Scanner;<br><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * ClassName: TomcatWebsocketListener</span><br><span class="hljs-comment"> * Package: com.memory.simplewebsocket.listener</span><br><span class="hljs-comment"> * Description:</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Author</span> Memory</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Create</span> 2024/10/5 10:20</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Version</span> 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ChatClient1</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">WebSocketListener</span> &#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">SERVER_URL</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;ws://localhost:8080/chat/1&quot;</span>;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">OkHttpClient</span> <span class="hljs-variable">client</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">OkHttpClient</span>();<br>        <span class="hljs-type">Request</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Request</span>.Builder().url(SERVER_URL).build();<br>        <span class="hljs-type">WebSocket</span> <span class="hljs-variable">webSocket</span> <span class="hljs-operator">=</span> client.newWebSocket(request, <span class="hljs-keyword">new</span> <span class="hljs-title class_">ChatClient1</span>());<br><br>        <span class="hljs-type">Scanner</span> <span class="hljs-variable">scanner</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Scanner</span>(System.in);<br>        System.out.println(<span class="hljs-string">&quot;请输入消息:&quot;</span>);<br><br>        <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) &#123;<br>            <span class="hljs-type">String</span> <span class="hljs-variable">message</span> <span class="hljs-operator">=</span> scanner.nextLine();<br><br>            <span class="hljs-keyword">if</span> (message.equals(<span class="hljs-string">&quot;exit&quot;</span>)) &#123;<br>                webSocket.close(<span class="hljs-number">1000</span>, <span class="hljs-string">&quot;Client is closing the connection&quot;</span>);<br>                <span class="hljs-keyword">break</span>;<br>            &#125;<br>            webSocket.send(message);<br>        &#125;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onOpen</span><span class="hljs-params">(WebSocket webSocket, okhttp3.Response response)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;连接已打开&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onMessage</span><span class="hljs-params">(WebSocket webSocket, String text)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;收到消息: &quot;</span> + text);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onClosing</span><span class="hljs-params">(WebSocket webSocket, <span class="hljs-type">int</span> code, String reason)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;连接已关闭: &quot;</span> + code + <span class="hljs-string">&quot; - &quot;</span> + reason);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onFailure</span><span class="hljs-params">(WebSocket webSocket, Throwable t, okhttp3.Response response)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;连接失败: &quot;</span> + t.getMessage());<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>依赖导入：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--spring-boot-starter-web--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--spring-boot-starter-websocket--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-websocket<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--spring-boot-starter-test--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-comment">&lt;!--okhttp--&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.squareup.okhttp3<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>okhttp<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>4.12.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>我使用的 SpringBoot 版本是 3.2.10，这里的 okhttp 版本也要是最新的 4.12.0，否则客户端启动会报错：</p>
<p><img src="http://blog.memory-life.xyz/image-20241005105327273.png" alt="image-20241005105327273"></p>
<p>这就是版本不兼容了，修改 okhttp 依赖版本即可：</p>
<p><img src="http://blog.memory-life.xyz/image-20241005104021109.png" alt="image-20241005104021109"></p>
<p><img src="http://blog.memory-life.xyz/image-20241005105839804.png" alt="image-20241005105839804"></p>
<p>编写 Websocket 配置类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.memory.simplewebsocket.config;<br><br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;<br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;<br><span class="hljs-keyword">import</span> org.springframework.web.socket.server.standard.ServerEndpointExporter;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> yuanyiwen</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2019-12-03 18:38</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@description</span></span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">WebSocketConfig</span> &#123;<br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> ServerEndpointExporter <span class="hljs-title function_">serverEndpointExporter</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ServerEndpointExporter</span>();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>启动服务端，</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">spring:</span><br>  <span class="hljs-attr">application:</span><br>    <span class="hljs-attr">name:</span> <span class="hljs-string">simple-websocket</span><br><span class="hljs-attr">server:</span><br>  <span class="hljs-attr">port:</span> <span class="hljs-number">8080</span><br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20241005135826514.png" alt="image-20241005135826514"></p>
<p>基于 Java 的 WebSocket 服务器端实现，它使用了 Jakarta WebSocket API，这里指定了 WebSocket 服务器端点的路径：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Component</span><br><span class="hljs-meta">@ServerEndpoint(&quot;/chat/&#123;userId&#125;&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TomcatWebsocketServer</span> &#123;<br>    <span class="hljs-comment">// 管理连接</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Map&lt;Long, Session&gt; clients = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span>&lt;&gt;();<br>    <span class="hljs-comment">// 日志打印</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">Logger</span> <span class="hljs-variable">logger</span> <span class="hljs-operator">=</span> LoggerFactory.getLogger(ServerEndpoint.class);<br>    <span class="hljs-comment">// 用户</span><br>    <span class="hljs-keyword">private</span> Long userId;<br><br>    ...................................<br>    &#125;<br></code></pre></td></tr></table></figure>

<p>服务端启动后，监听本机 8080 端口，等待客户端连接：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment">    * 开启连接, 触发</span><br><span class="hljs-comment">    *</span><br><span class="hljs-comment">    * <span class="hljs-doctag">@param</span> session 会话</span><br><span class="hljs-comment">    * <span class="hljs-doctag">@param</span> userId  用户</span><br><span class="hljs-comment">    */</span><br>   <span class="hljs-meta">@OnOpen</span><br>   <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onOpen</span><span class="hljs-params">(Session session, <span class="hljs-meta">@PathParam(&quot;userId&quot;)</span> Long userId)</span> &#123;<br>       <span class="hljs-built_in">this</span>.userId = userId;<br>       <span class="hljs-comment">// 存储用户和对应会话</span><br>       clients.put(userId, session);<br>       logger.info(String.format(<span class="hljs-string">&quot;用户 %d 已上线，新的连接 ------------------&gt; %s&quot;</span>, <span class="hljs-built_in">this</span>.userId, session.getId()));<br>   &#125;<br></code></pre></td></tr></table></figure>

<p>我们编写了两个客户端类，模拟两个用户在线连接到服务器进行通信：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * ClassName: TomcatWebsocketListener</span><br><span class="hljs-comment"> * Package: com.memory.simplewebsocket.listener</span><br><span class="hljs-comment"> * Description:</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Author</span> Memory</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Create</span> 2024/10/5 10:20</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@Version</span> 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ChatClient1</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">WebSocketListener</span> &#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">SERVER_URL</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;ws://localhost:8080/chat/1&quot;</span>;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">OkHttpClient</span> <span class="hljs-variable">client</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">OkHttpClient</span>();<br>        <span class="hljs-type">Request</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Request</span>.Builder().url(SERVER_URL).build();<br>        <span class="hljs-type">WebSocket</span> <span class="hljs-variable">webSocket</span> <span class="hljs-operator">=</span> client.newWebSocket(request, <span class="hljs-keyword">new</span> <span class="hljs-title class_">ChatClient1</span>());<br><br>        <span class="hljs-type">Scanner</span> <span class="hljs-variable">scanner</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Scanner</span>(System.in);<br>        System.out.println(<span class="hljs-string">&quot;请输入消息:&quot;</span>);<br><br>        <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) &#123;<br>            <span class="hljs-type">String</span> <span class="hljs-variable">message</span> <span class="hljs-operator">=</span> scanner.nextLine();<br><br>            <span class="hljs-keyword">if</span> (message.equals(<span class="hljs-string">&quot;exit&quot;</span>)) &#123;<br>                webSocket.close(<span class="hljs-number">1000</span>, <span class="hljs-string">&quot;Client is closing the connection&quot;</span>);<br>                <span class="hljs-keyword">break</span>;<br>            &#125;<br>            webSocket.send(message);<br>        &#125;<br>    &#125;<br><br>  ......................................................<br>  &#125;<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20241005140705618.png" alt="image-20241005140705618"></p>
<p><img src="http://blog.memory-life.xyz/image-20241005140714226.png" alt="image-20241005140714226"></p>
<p>用户上线后发送消息，显然广播成功了，都能收到对方发来的消息，再看看服务端这边：</p>
<p><img src="http://blog.memory-life.xyz/image-20241005140909624.png" alt="image-20241005140909624"></p>
<p>显然服务端能正常管理登录用户和对应会话资源，并处理消息广播，让所有在线用户都能收到消息</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 收到消息, 触发</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> message 消息</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> session 会话</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@OnMessage</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onMessage</span><span class="hljs-params">(String message, Session session)</span> &#123;<br>    logger.info(String.format(<span class="hljs-string">&quot;收到来自 %d 的消息 ------------------&gt; %s&quot;</span>, userId, message));<br>    <span class="hljs-comment">// 向全体在线成员推送这条消息</span><br>    sendMessageFromOneToAll(message);<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment">    * 广播消息</span><br><span class="hljs-comment">    *</span><br><span class="hljs-comment">    * <span class="hljs-doctag">@param</span> message 消息</span><br><span class="hljs-comment">    */</span><br>   <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">sendMessageFromOneToAll</span><span class="hljs-params">(String message)</span> &#123;<br>       clients.forEach((userId, session) -&gt; &#123;<br>           <span class="hljs-keyword">try</span> &#123;<br>               session.getBasicRemote().sendText(String.format(<span class="hljs-string">&quot;广播来自 %d 的消息 ------------------&gt; %s%n&quot;</span>, <span class="hljs-built_in">this</span>.userId, message));<br>           &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>               e.printStackTrace();<br>           &#125;<br>       &#125;);<br>   &#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>2024 年 10 月 5 日</p>
</blockquote>
<p>再实现两个网页版客户端，交流通信会更加直观。</p>
<p>两个客户端源码基本相同，就这一套：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>在线用户二号<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;chat&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;messageInput&quot;</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">&quot;Type your message&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;sendMessage()&quot;</span>&gt;</span>Send<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="language-javascript"></span><br><span class="language-javascript">      <span class="hljs-keyword">const</span> socket = <span class="hljs-keyword">new</span> <span class="hljs-title class_">WebSocket</span>(<span class="hljs-string">&quot;ws://localhost:8080/chat/2&quot;</span>);</span><br><span class="language-javascript"></span><br><span class="language-javascript">      socket.<span class="hljs-property">onopen</span> = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> &#123;</span><br><span class="language-javascript">        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;WebSocket connection opened:&quot;</span>, event);</span><br><span class="language-javascript">      &#125;;</span><br><span class="language-javascript"></span><br><span class="language-javascript">      socket.<span class="hljs-property">onmessage</span> = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> &#123;</span><br><span class="language-javascript">        <span class="hljs-keyword">const</span> messageDiv = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&quot;chat&quot;</span>);</span><br><span class="language-javascript">        <span class="hljs-keyword">const</span> messageParagraph = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">createElement</span>(<span class="hljs-string">&quot;p&quot;</span>);</span><br><span class="language-javascript">        messageParagraph.<span class="hljs-property">textContent</span> = event.<span class="hljs-property">data</span>;</span><br><span class="language-javascript">        messageDiv.<span class="hljs-title function_">appendChild</span>(messageParagraph);</span><br><span class="language-javascript">      &#125;;</span><br><span class="language-javascript"></span><br><span class="language-javascript">      socket.<span class="hljs-property">onclose</span> = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> &#123;</span><br><span class="language-javascript">        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;WebSocket connection closed:&quot;</span>, event);</span><br><span class="language-javascript">      &#125;;</span><br><span class="language-javascript"></span><br><span class="language-javascript">      <span class="hljs-keyword">function</span> <span class="hljs-title function_">sendMessage</span>(<span class="hljs-params"></span>) &#123;</span><br><span class="language-javascript">        <span class="hljs-keyword">const</span> messageInput = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&quot;messageInput&quot;</span>);</span><br><span class="language-javascript">        <span class="hljs-keyword">const</span> message = messageInput.<span class="hljs-property">value</span>;</span><br><span class="language-javascript">        socket.<span class="hljs-title function_">send</span>(message);</span><br><span class="language-javascript">        messageInput.<span class="hljs-property">value</span> = <span class="hljs-string">&quot;&quot;</span>;</span><br><span class="language-javascript">      &#125;</span><br><span class="language-javascript">    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>这里重新设置下服务端广播逻辑，只广播当前非当前会话的消息，因为当前会话的消息就是自己的消息，不需要给自己广播，特殊处理：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment">   * 收到消息, 触发</span><br><span class="hljs-comment">   *</span><br><span class="hljs-comment">   * <span class="hljs-doctag">@param</span> message 消息</span><br><span class="hljs-comment">   * <span class="hljs-doctag">@param</span> session 会话</span><br><span class="hljs-comment">   */</span><br>  <span class="hljs-meta">@OnMessage</span><br>  <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">onMessage</span><span class="hljs-params">(String message, Session session)</span> &#123;<br>      logger.info(String.format(<span class="hljs-string">&quot;收到来自 %d 的消息 ------------------&gt; %s&quot;</span>, userId, message));<br>      <span class="hljs-comment">// 向全体在线成员推送这条消息</span><br>      sendMessageFromOneToAll(session, message);<br>  &#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment">    * 广播消息</span><br><span class="hljs-comment">    *</span><br><span class="hljs-comment">    * <span class="hljs-doctag">@param</span> session 会话</span><br><span class="hljs-comment">    * <span class="hljs-doctag">@param</span> message 消息</span><br><span class="hljs-comment">    */</span><br>   <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">sendMessageFromOneToAll</span><span class="hljs-params">(Session session, String message)</span> &#123;<br>       clients.forEach((userId, client) -&gt; &#123;<br>           <span class="hljs-keyword">try</span> &#123;<br>               <span class="hljs-keyword">if</span> (client != session) &#123;<br>                   client.getBasicRemote().sendText(String.format(<span class="hljs-string">&quot;广播来自 %d 的消息 ------------------&gt; %s%n&quot;</span>, <span class="hljs-built_in">this</span>.userId, message));<br>               &#125; <span class="hljs-keyword">else</span> &#123;<br>                   client.getBasicRemote().sendText(String.format(<span class="hljs-string">&quot;自己发送的消息 ------------------&gt; %s%n&quot;</span>, message));<br>               &#125;<br>           &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>               e.printStackTrace();<br>           &#125;<br>       &#125;);<br>   &#125;<br></code></pre></td></tr></table></figure>

<p>就这样，我们实现了两个在线用户的通信交流，相当有趣，这也是时隔一年多以来再次系统地研究如何实现实时通信：</p>
<p><img src="http://blog.memory-life.xyz/image-20241005143136271.png" alt="image-20241005143136271"></p>
<p><img src="http://blog.memory-life.xyz/image-20241005143131814.png" alt="image-20241005143131814"></p>
<p>很好玩啊，总算亲手实践了 Websocket 实现实时通信。</p>
<h2 id="windows-脚本编程"><a href="#windows-脚本编程" class="headerlink" title="windows 脚本编程"></a>windows 脚本编程</h2><blockquote>
<p>2024 年 7 月 13 日</p>
</blockquote>
<p><img src="http://blog.memory-life.xyz/image-20240713075227778.png" alt="image-20240713075227778"></p>
<p><img src="http://blog.memory-life.xyz/image-20240713075309570.png" alt="image-20240713075309570"></p>
<h2 id="毕设小项目"><a href="#毕设小项目" class="headerlink" title="毕设小项目"></a>毕设小项目</h2><blockquote>
<p>2024 年 7 月 21 日</p>
</blockquote>
<p>今天尝试跑几个 Spring + Vue 项目，看看能不能成功运行。</p>
<h2 id="MemorySearch-忆搜阁"><a href="#MemorySearch-忆搜阁" class="headerlink" title="MemorySearch 忆搜阁"></a>MemorySearch 忆搜阁</h2><blockquote>
<p>2024 年 8 月 8 日</p>
</blockquote>
<p>今天早上刷知乎，看到了这样一段有意义的话，原文我已经记不大清楚，大致意思是这样的：</p>
<p>我面试过很多求职者，现在的 IT 行业求职的人普遍太水了，只要你稍微努努力都能甩开身边人一大截。</p>
<p>像我以前面试过的那些人，问的那些简单的八股文都很难回答上来，计算机专业最基本的科学素养都没有。</p>
<p>没什么可问的就盘问项目吧，可很多人也是支支吾吾说不清楚，不论是个人项目还是工作中参与到的企业项目，开发过程都跟自己没关系一样好像。</p>
<p>我来教你怎么把项目说清楚，面试官不管从哪个角度问都能回答得滴水不漏：</p>
<p>你整体回顾一遍项目，分别从三个角度来写这个项目是做什么用的，里面涉及到了哪些技术亮点或难点，你又是怎么解决的。</p>
<p>写这个的目的不是为了再巩固一遍如何分析这个项目所用到的技术栈，完全不需要这样细致入微的描述。</p>
<p>只需要从宏观角度上简洁明了的介绍这个项目到底是怎么回事就行，不管别人怎么问，你都能从容不迫面不改色地聊项目，这样在面试中会很加分。</p>
<p><strong>那么，开始吧，我已经完全过了一遍这个项目了，开始动手写一篇文章。</strong></p>
<blockquote>
<p>2024 年 8 月 8 日</p>
</blockquote>
<p>这个项目是一个基于 <strong>Spring Boot + Elastic Stack 技术栈 + Vue.js</strong> 的<code>聚合搜索中台</code>。它不仅是一个强大的搜索引擎，更是一个内容丰富的社区平台。</p>
<p>什么是聚合搜索中台，它最核心的功能就是给使用者提供了丰富的搜索搜索体验。我们经常逛浏览器，打开任何一个搜索引擎，比如百度必应谷歌，在搜索框中查找资料检索数据很方便，体验很好。</p>
<p>所以我也想动手实现这样一个搜索中台，不需要实现很多花哨的操作。像平时做那些简单的后台管理系统项目时，也有实现过简单的搜索功能，根据某个字段的 id 或者描述，写最简单的 SQL 语句加上简单的条件判断，就实现简单的数据查询。</p>
<p>但这样的搜索功能是远远不够的，我注意到了 Elasticsearch，了解到了 Elastic Stack 技术栈，这样的工具很适合用来实现在海量数据中作检索和分析，借此机会也能真正实践运用 Elastic Stack 技术栈。</p>
<p>我连接到了 Elastic Stack 技术栈中的很多有意思的东西：ES 的安装，DSL 查询语句（布尔查询，聚合查询，复合查询等），下载了 Kibana ，在 dash Board 处能清晰地写 DSL 语句。Elasticseach 是一个文档型数据库，ES 和 MySQL 之间经常会有比较。我学习了如何插入索引，更新索引，新增文档数据，作简单的布尔查询。除此之外还有分词器的安装和使用，让我更清晰地理解了 ES 构建索引和基于倒排索引查询文档的底层原理。</p>
<p>我最关心的还是两点：如何使用 Elasticseach 实现高级的查询效果呢，我学习了关键词语高亮，搜索词条建议，热门话题分析等 DSL 语句的编写，用很多的 Demo 语句实践了这些丰富的查询功能。</p>
<p>ElastidSearch 中的数据都要从数据库 MySQL 中同步过来，所以我掌握了 Logstash 数据同步管道的相关配置，学会了如何使用 Logstash 监听本地 MySQL 变更的数据，并同步指定的字段到 Elasticsearch 中。比如说我要实现诗词的关键词语高亮，搜索词条建议和热门话题分析等功能，我会选择同步 MySQL 数据库中诗词数据对应的几个字段，同步这些字段的数据到 Elasticseach 中。</p>
<p><strong>可说的太多了吧，我怎么感觉这种方式不太靠谱，因为写完这段文字之后我都不想再回头看一遍。。</strong></p>
<p>除了简历上提到的：使用 Spring AOP 切面编程实现权限校验和全局请求拦截，配置定时任务抓取外源数据并解析到本地数据库，深入学习 Elastic Stack 技术栈，掌握倒排索引，分词机制，查询 DSL，实现关键词语高亮，搜索词条建议，热门话题分析等功能，运用多种设计模式简化编码提高效率，自主搭建 Logstash 数据同步管道同步数据，使用 CompletableFuture 异步编程减少批量插入数据的等待时间。</p>
<p>还有：限流，Redis 实现热门搜索统计以及缓存性能优化，互动创作平台等功能。</p>
<h2 id="Github-优质项目"><a href="#Github-优质项目" class="headerlink" title="Github 优质项目"></a>Github 优质项目</h2><blockquote>
<p>2024 年 9 月 21 日</p>
</blockquote>
<p>变化挺大。这讯飞星火还更新了嘛，</p>
<p><img src="http://blog.memory-life.xyz/image-20240921194602183.png" alt="image-20240921194602183"></p>
<p>掘金有个大模型帖子站点，挺不错。</p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7136367341536804871">Electron 小白入门手册——跨端桌面应用开发的前世今生简史今天我们就从原生桌面开发、QT、NW、Electron、 - 掘金 (juejin.cn)</a></p>
<p>疯狂地涉猎了桌面开发，移动端开发等领域，圆满了。</p>
<p><a target="_blank" rel="noopener" href="https://chencoding.top:8090/#/">优秀的开源项目 - Java 陈序员 (chencoding.top)</a></p>
<h2 id="AI-图书管理"><a href="#AI-图书管理" class="headerlink" title="AI 图书管理"></a>AI 图书管理</h2><blockquote>
<p>2024 年 9 月 24 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://gitee.com/falle22222n-leaves/vue_-book-manage-system_backend">GPT 智能图书管理系统后台 Vue2-SpringBoot2</a></p>
<p><a target="_blank" rel="noopener" href="https://gitee.com/falle22222n-leaves/vue_-book-manage-system">GPT 智能图书管理系统前台 Vue2-SpringBoot2</a></p>
<p><img src="http://blog.memory-life.xyz/image-20240923092639180.png" alt="image-20240923092639180"></p>
<p><img src="http://blog.memory-life.xyz/image-20240923093021291.png" alt="image-20240923093021291"></p>
<p><img src="http://blog.memory-life.xyz/image-20240923093036696.png" alt="image-20240923093036696"></p>
<p><img src="http://blog.memory-life.xyz/image-20240923093101909.png" alt="image-20240923093101909"></p>
<p><img src="http://blog.memory-life.xyz/image-20240923093110935.png" alt="image-20240923093110935"></p>
<p>这个项目还是曹老板上网扒下来的，我一看就知道是整合星球内部项目的，做的相当完善，学习了。</p>
<blockquote>
<p>2024 年 9 月 25 日</p>
</blockquote>
<p>书接上回，今天总算完成了秋招面试中的第二场流程面试 - 深圳捷顺科技一面，期望后续会有消息吧。</p>
<p>下午闲来无事，拉下来跑跑项目学习下，了解认识程序员小白条，是个很有趣的人。</p>
<p><a target="_blank" rel="noopener" href="https://luoye6.github.io/link/">友情链接 | 小白条的个人博客 (luoye6.github.io)</a></p>
<p>看过了一遍 READE,md 文档，基本了解了整个项目的核心业务逻辑及其功能实现，一年多以来的 bug 跟踪及优化调整，基本掌握。</p>
<h3 id="项目启动-2"><a href="#项目启动-2" class="headerlink" title="项目启动"></a>项目启动</h3><p>后端启动完成，建库建表完成，修改数据库连接配置，解决 yaml 配置文件中文编码问题，Swagger 接口文档功能正常。</p>
<p><img src="http://blog.memory-life.xyz/image-20240925162612612.png" alt="image-20240925162612612"></p>
<p><img src="http://blog.memory-life.xyz/image-20240925162353269.png" alt="image-20240925162353269"></p>
<p>前端项目启动完毕，基本理清页面目录结构，登录失败，奶奶的没有用户数据。</p>
<p><img src="http://blog.memory-life.xyz/image-20240925163906760.png" alt="image-20240925163906760"></p>
<p>加小白条好友位，要一下模拟数据资源。</p>
<h2 id="Spring-模块"><a href="#Spring-模块" class="headerlink" title="Spring 模块"></a>Spring 模块</h2><blockquote>
<p>2024 年 10 月 4 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://gitee.com/code_artist/spring">spring: Spring 学习相关代码 (gitee.com)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20241004160256897.png" alt="image-20241004160256897"></p>
<p>一个小时的时间里，从我收录的两个 Sprign Demo 代码专栏中，系统学习了一遍 SpringAOP 相关知识。</p>
<p><strong>特别是切点表达式和通知的使用方法。</strong></p>
<p>拦截器/过滤器</p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7367679976869494799?share_token=326d1d43-847e-4425-9e59-a15fad9e530b">谈谈 Spring 的过滤器和拦截器我们在进行 Web 应用开发时，时常需要对请求进行拦截或处理，故 Spring 为我 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s/Mixqj_d7B-zIh4sgQRIzLw">从使用教程、实现原理、差异对比全方面带你玩转业务系统中高频使用的过滤器与拦截器 (qq.com)</a></p>
<p>限流算法</p>
<p>RabbitMQ</p>
<p>Docker 部署</p>
<p>Guava</p>
<p>MyBatis-Plus</p>
<p>函数式编程</p>
<p>SpringMVC 扩展点</p>
<p>Stream 流</p>
<p>LocalDateTime</p>
<p>JWT</p>
<p>生产者/消费者</p>
<p>[05 有哪几种实现生产者消费者模式的方法？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Java">https://learn.lianglianglee.com/专栏/Java</a> 并发编程 78 讲-完/05 有哪几种实现生产者消费者模式的方法？.md)</p>
<h2 id="商城"><a href="#商城" class="headerlink" title="商城"></a>商城</h2><blockquote>
<p>2025 年 1 月 10 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7441227963492253735">再见 Jenkins！一款更适合国人的自动化部署工具，贼带劲！在开发或生产环境中，我们有时候会上服务器器然后敲命令来部署项 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://www.macrozheng.com/">项目主页 | mall 学习教程 (macrozheng.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://gitee.com/macrozheng">macro (macrozheng) - Gitee.com</a></p>
<blockquote>
<p>2025 年 1 月 14 日</p>
</blockquote>
<p>下午四点多，启动后端四个模块：<code>MallAdminApplication</code>，<code>MallDemoApplication</code>，<code>MallPortalAppliaction</code>，<code>MallSearchApplication</code>。</p>
<p>修改下配置，MySQL，MongoDB，RabbitMQ，Elasticsearch。</p>
<blockquote>
<p>2025 年 1 月 15 日</p>
</blockquote>
<p>尝试起下前端页面。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.macrozheng.com/">项目主页 | mall 学习教程 (macrozheng.com)</a></p>
<p>官网能看到双端预览效果，商城系统看多了挺头疼，我想想应该怎么改才好，要是能直接拿过来该多好。</p>
<p>不过自己当然也希望能学点新东西，捋清楚代码业务逻辑，写业务能更加熟练点，考虑面更广泛一些，也想能多了解下前端知识。</p>
<p>Vue 从来没有系统学习过，最近这些项目确实看得脑袋昏昏沉沉。</p>
<p>后台管理前端项目起来了。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">Your application is running here: http://localhost:8090<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250115152933952.png" alt="image-20250115152933952"></p>
<p>移动端还没，不过为什么移动端项目缺少 package.json 文件呢。</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">15</span>:<span class="hljs-number">24</span>:<span class="hljs-number">51</span>.<span class="hljs-number">213</span> 项目 mall-app-web 开始编译<br><span class="hljs-attribute">15</span>:<span class="hljs-number">24</span>:<span class="hljs-number">51</span>.<span class="hljs-number">926</span> 正在下载编译工具，请稍后...<br><span class="hljs-attribute">15</span>:<span class="hljs-number">26</span>:<span class="hljs-number">32</span>.<span class="hljs-number">145</span> 编译工具下载成功<br><span class="hljs-attribute">15</span>:<span class="hljs-number">26</span>:<span class="hljs-number">33</span>.<span class="hljs-number">673</span> 请注意运行模式下，因日志输出、sourcemap以及未压缩源码等原因，性能和包体积，均不及发行模式。<br><span class="hljs-attribute">15</span>:<span class="hljs-number">26</span>:<span class="hljs-number">33</span>.<span class="hljs-number">844</span> 正在编译中...<br><span class="hljs-attribute">15</span>:<span class="hljs-number">26</span>:<span class="hljs-number">34</span>.<span class="hljs-number">949</span>  INFO  Starting development server...<br><span class="hljs-attribute">15</span>:<span class="hljs-number">26</span>:<span class="hljs-number">44</span>.<span class="hljs-number">664</span> 预编译器错误：代码使用了scss/sass语言，但未安装相应的编译器插件，正在从插件市场安装该插件:<br><span class="hljs-attribute">15</span>:<span class="hljs-number">26</span>:<span class="hljs-number">44</span>.<span class="hljs-number">665</span> https://ext.dcloud.net.cn/plugin?name=compile-node-sass at App.vue:<span class="hljs-number">1</span><br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250115152825451.png" alt="image-20250115152825451"></p>
<p><img src="http://blog.memory-life.xyz/image-20250115153120208.png" alt="image-20250115153120208"></p>
<blockquote>
<p>2025 年 2 月 24 日</p>
</blockquote>
<p>今天还不计划该写代码，先根据电影院网上订票系统设计与实现，对应精简下基于 JavaWeb 的汽配销售管理系统设计与实现。</p>
<p>项目官网：<a target="_blank" rel="noopener" href="https://www.macrozheng.com/">《mall 学习教程》</a></p>
<h1 id="毕业设计"><a href="#毕业设计" class="headerlink" title="毕业设计"></a>毕业设计</h1><blockquote>
<p>2025 年 1 月 9 日</p>
</blockquote>
<p>从现在开始逐步完善下毕设作品和论文撰写吧。</p>
<p>昨天下午起了项目，数据库建表 sql 语句文件都有，不过却缺少一个关键角色表，这些博主们老奸巨猾的操作。</p>
<p>新增角色表：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `auth`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> auth<br>(<br>    auth_id        <span class="hljs-type">INT</span>(<span class="hljs-number">10</span>)      <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> AUTO_INCREMENT COMMENT <span class="hljs-string">&#x27;授权ID，主键&#x27;</span>,<br>    user_group     <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">64</span>) COMMENT <span class="hljs-string">&#x27;用户组&#x27;</span>,<br>    mod_name       <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;模块名&#x27;</span>,<br>    table_name     <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;表名&#x27;</span>,<br>    page_title     <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;页面标题&#x27;</span>,<br>    path           <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;路由路径&#x27;</span>,<br>    position       <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>)  <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;位置&#x27;</span>,<br>    mode           <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>)  <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">&#x27;_blank&#x27;</span> COMMENT <span class="hljs-string">&#x27;跳转方式&#x27;</span>,<br>    `<span class="hljs-keyword">add</span>`            TINYINT(<span class="hljs-number">3</span>)   <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">1</span> COMMENT <span class="hljs-string">&#x27;是否可增加&#x27;</span>,<br>    `del`            TINYINT(<span class="hljs-number">3</span>)   <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">1</span> COMMENT <span class="hljs-string">&#x27;是否可删除&#x27;</span>,<br>    `<span class="hljs-keyword">set</span>`            TINYINT(<span class="hljs-number">3</span>)   <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">1</span> COMMENT <span class="hljs-string">&#x27;是否可修改&#x27;</span>,<br>    `<span class="hljs-keyword">get</span>`            TINYINT(<span class="hljs-number">3</span>)   <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">1</span> COMMENT <span class="hljs-string">&#x27;是否可查看&#x27;</span>,<br>    field_add      TEXT COMMENT <span class="hljs-string">&#x27;添加字段&#x27;</span>,<br>    field_set      TEXT COMMENT <span class="hljs-string">&#x27;修改字段&#x27;</span>,<br>    field_get      TEXT COMMENT <span class="hljs-string">&#x27;查询字段&#x27;</span>,<br>    table_nav_name <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">500</span>) COMMENT <span class="hljs-string">&#x27;跨表导航名称&#x27;</span>,<br>    table_nav      <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">500</span>) COMMENT <span class="hljs-string">&#x27;跨表导航&#x27;</span>,<br>    `option`         TEXT COMMENT <span class="hljs-string">&#x27;配置&#x27;</span>,<br>    create_time    <span class="hljs-type">TIMESTAMP</span>    <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> COMMENT <span class="hljs-string">&#x27;创建时间&#x27;</span>,<br>    update_time    <span class="hljs-type">TIMESTAMP</span>    <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> COMMENT <span class="hljs-string">&#x27;更新时间&#x27;</span>,<br>    <span class="hljs-keyword">PRIMARY</span> KEY (auth_id)<br>) COMMENT <span class="hljs-operator">=</span><span class="hljs-string">&#x27;用户权限管理表&#x27;</span>;<br></code></pre></td></tr></table></figure>

<p>启动项目成功。</p>
<p><img src="http://blog.memory-life.xyz/image-20250109151140651.png" alt="image-20250109151140651"></p>
<p><img src="http://blog.memory-life.xyz/image-20250109151124609.png" alt="image-20250109151124609"></p>
<p>不过登录时控制台出现报错，是数据库字符集问题：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash">Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b10b7cc]<br>2025-01-09 13:14:53.015 ERROR 8720 --- [io-5000-exec-10] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() <span class="hljs-keyword">for</span> servlet [dispatcherServlet] <span class="hljs-keyword">in</span> context with path [/api] threw exception [Request processing failed; nested exception is org.springframework.jdbc.UncategorizedSQLException:<br><span class="hljs-comment">### Error querying database.  Cause: java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation &#x27;=&#x27;</span><br><span class="hljs-comment">### The error may exist in file [D:\Project\springboot汽车销售管理系统[编号：project97848]\project\target\classes\mapper\BaseMapper.xml]</span><br><span class="hljs-comment">### The error may involve defaultParameterMap</span><br><span class="hljs-comment">### The error occurred while setting parameters</span><br><span class="hljs-comment">### SQL: select * from `auth` WHERE `user_group` = &#x27;管理员&#x27;</span><br><span class="hljs-comment">### Cause: java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation &#x27;=&#x27;</span><br>; uncategorized SQLException; SQL state [HY000]; error code [1267]; Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) <span class="hljs-keyword">for</span> operation <span class="hljs-string">&#x27;=&#x27;</span>; nested exception is java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) <span class="hljs-keyword">for</span> operation <span class="hljs-string">&#x27;=&#x27;</span>] with root cause<br></code></pre></td></tr></table></figure>

<p>就这张表特殊，改掉。</p>
<p><img src="http://blog.memory-life.xyz/image-20250109151508690.png" alt="image-20250109151508690"></p>
<p>不信了，这样竟然还不行。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">drop</span> database if <span class="hljs-keyword">exists</span> `mall`;<br><span class="hljs-keyword">create</span> database if <span class="hljs-keyword">not</span> <span class="hljs-keyword">exists</span> `mall`<br><span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> utf8mb4<br><span class="hljs-keyword">COLLATE</span> utf8mb4_general_ci;<br>use `mall`;<br></code></pre></td></tr></table></figure>

<p>起来啦，果然删除重新建库建表完美解决问题。</p>
<p><img src="http://blog.memory-life.xyz/image-20250109161056301.png" alt="image-20250109161056301"></p>
<blockquote>
<p>2025 年 2 月 24 日</p>
</blockquote>
<p>今天下午三点多简单过了一遍优秀毕业论文，六篇毕业论文五花八门的，最终选定这一篇作为参考：电影院网上订票系统设计与实现。</p>
<blockquote>
<p>2025 年 2 月 26 日</p>
</blockquote>
<p>基本搞清楚后台管理系统控制器逻辑。</p>
<blockquote>
<p>2025 年 2 月 28 日</p>
</blockquote>
<p>这张数据库表是关键。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql">pms_product_category<br></code></pre></td></tr></table></figure>

<p>获取商品分类及其子分类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 获取商品分类及其子分类</span><br><span class="hljs-comment"> */</span><br>List&lt;PmsProductCategoryWithChildrenItem&gt; <span class="hljs-title function_">listWithChildren</span><span class="hljs-params">()</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java">&lt;select id=<span class="hljs-string">&quot;selectByExample&quot;</span> parameterType=<span class="hljs-string">&quot;com.macro.mall.model.PmsBrandExample&quot;</span> resultMap=<span class="hljs-string">&quot;BaseResultMap&quot;</span>&gt;<br>  select<br>  &lt;<span class="hljs-keyword">if</span> test=<span class="hljs-string">&quot;distinct&quot;</span>&gt;<br>    distinct<br>  &lt;/<span class="hljs-keyword">if</span>&gt;<br>  &lt;include refid=<span class="hljs-string">&quot;Base_Column_List&quot;</span> /&gt;<br>  from pms_brand<br>  &lt;<span class="hljs-keyword">if</span> test=<span class="hljs-string">&quot;_parameter != null&quot;</span>&gt;<br>    &lt;include refid=<span class="hljs-string">&quot;Example_Where_Clause&quot;</span> /&gt;<br>  &lt;/<span class="hljs-keyword">if</span>&gt;<br>  &lt;<span class="hljs-keyword">if</span> test=<span class="hljs-string">&quot;orderByClause != null&quot;</span>&gt;<br>    order by $&#123;orderByClause&#125;<br>  &lt;/<span class="hljs-keyword">if</span>&gt;<br>&lt;/select&gt;<br></code></pre></td></tr></table></figure>

<p>获取品牌列表。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@ApiOperation(value = &quot;根据品牌名称分页获取品牌列表&quot;)</span><br>  <span class="hljs-meta">@RequestMapping(value = &quot;/list&quot;, method = RequestMethod.GET)</span><br>  <span class="hljs-meta">@ResponseBody</span><br>  <span class="hljs-keyword">public</span> CommonResult&lt;CommonPage&lt;PmsBrand&gt;&gt; <span class="hljs-title function_">getList</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(value = &quot;keyword&quot;, required = false)</span> String keyword,</span><br><span class="hljs-params">                                                    <span class="hljs-meta">@RequestParam(value = &quot;showStatus&quot;, required = false)</span> Integer showStatus,</span><br><span class="hljs-params">                                                    <span class="hljs-meta">@RequestParam(value = &quot;pageNum&quot;, defaultValue = &quot;1&quot;)</span> Integer pageNum,</span><br><span class="hljs-params">                                                    <span class="hljs-meta">@RequestParam(value = &quot;pageSize&quot;, defaultValue = &quot;5&quot;)</span> Integer pageSize)</span> &#123;<br>      List&lt;PmsBrand&gt; brandList = brandService.listBrand(keyword, showStatus, pageNum, pageSize);<br>      <span class="hljs-keyword">return</span> CommonResult.success(CommonPage.restPage(brandList));<br>  &#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java">&lt;select id=<span class="hljs-string">&quot;selectByExample&quot;</span> parameterType=<span class="hljs-string">&quot;com.macro.mall.model.PmsBrandExample&quot;</span> resultMap=<span class="hljs-string">&quot;BaseResultMap&quot;</span>&gt;<br>   select<br>   &lt;<span class="hljs-keyword">if</span> test=<span class="hljs-string">&quot;distinct&quot;</span>&gt;<br>     distinct<br>   &lt;/<span class="hljs-keyword">if</span>&gt;<br>   &lt;include refid=<span class="hljs-string">&quot;Base_Column_List&quot;</span> /&gt;<br>   from pms_brand<br>   &lt;<span class="hljs-keyword">if</span> test=<span class="hljs-string">&quot;_parameter != null&quot;</span>&gt;<br>     &lt;include refid=<span class="hljs-string">&quot;Example_Where_Clause&quot;</span> /&gt;<br>   &lt;/<span class="hljs-keyword">if</span>&gt;<br>   &lt;<span class="hljs-keyword">if</span> test=<span class="hljs-string">&quot;orderByClause != null&quot;</span>&gt;<br>     order by $&#123;orderByClause&#125;<br>   &lt;/<span class="hljs-keyword">if</span>&gt;<br> &lt;/select&gt;<br></code></pre></td></tr></table></figure>

<p><strong>品牌分类总表</strong></p>
<table>
<thead>
<tr>
<th align="center">品牌 ID</th>
<th align="center">品牌名称</th>
<th align="center">所属分类</th>
<th align="center">国家</th>
<th align="center">成立时间</th>
<th align="center">代表产品线</th>
<th align="center">品牌档次</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1</td>
<td align="center">博世 (Bosch)</td>
<td align="center">维修保养/车载电器</td>
<td align="center">德国</td>
<td align="center">1886</td>
<td align="center">燃油泵、刹车片、车载电器</td>
<td align="center">高端</td>
</tr>
<tr>
<td align="center">2</td>
<td align="center">曼牌 (MANN)</td>
<td align="center">维修保养</td>
<td align="center">德国</td>
<td align="center">1941</td>
<td align="center">滤清器</td>
<td align="center">中高端</td>
</tr>
<tr>
<td align="center">3</td>
<td align="center">美孚 (Mobil)</td>
<td align="center">维修保养</td>
<td align="center">美国</td>
<td align="center">1882</td>
<td align="center">全合成润滑油</td>
<td align="center">高端</td>
</tr>
<tr>
<td align="center">4</td>
<td align="center">布雷博 (Brembo)</td>
<td align="center">改装件/维修保养</td>
<td align="center">意大利</td>
<td align="center">1961</td>
<td align="center">刹车卡钳、刹车盘</td>
<td align="center">高端</td>
</tr>
<tr>
<td align="center">5</td>
<td align="center">70 迈</td>
<td align="center">车载电器</td>
<td align="center">中国</td>
<td align="center">2016</td>
<td align="center">行车记录仪</td>
<td align="center">中端</td>
</tr>
<tr>
<td align="center">6</td>
<td align="center">盯盯拍</td>
<td align="center">车载电器</td>
<td align="center">中国</td>
<td align="center">2013</td>
<td align="center">智能行车记录仪</td>
<td align="center">中端</td>
</tr>
<tr>
<td align="center">7</td>
<td align="center">飞利浦 (Philips)</td>
<td align="center">车载电器</td>
<td align="center">荷兰</td>
<td align="center">1891</td>
<td align="center">车载空气净化器</td>
<td align="center">高端</td>
</tr>
<tr>
<td align="center">8</td>
<td align="center">牧宝</td>
<td align="center">汽车装饰</td>
<td align="center">中国</td>
<td align="center">1994</td>
<td align="center">真皮座椅套</td>
<td align="center">中高端</td>
</tr>
<tr>
<td align="center">9</td>
<td align="center">尼罗河</td>
<td align="center">汽车装饰</td>
<td align="center">中国</td>
<td align="center">2005</td>
<td align="center">冰丝座椅套</td>
<td align="center">经济型</td>
</tr>
<tr>
<td align="center">10</td>
<td align="center">HKS</td>
<td align="center">改装件</td>
<td align="center">日本</td>
<td align="center">1973</td>
<td align="center">涡轮套件、排气系统</td>
<td align="center">高端</td>
</tr>
<tr>
<td align="center">11</td>
<td align="center">雅泛迪 (Advanti)</td>
<td align="center">改装件</td>
<td align="center">新加坡</td>
<td align="center">1998</td>
<td align="center">轻量化轮毂</td>
<td align="center">中高端</td>
</tr>
<tr>
<td align="center">12</td>
<td align="center">特斯拉 (Tesla)</td>
<td align="center">全新整车</td>
<td align="center">美国</td>
<td align="center">2003</td>
<td align="center">新能源整车</td>
<td align="center">高端</td>
</tr>
<tr>
<td align="center">13</td>
<td align="center">丰田 (Toyota)</td>
<td align="center">全新整车</td>
<td align="center">日本</td>
<td align="center">1937</td>
<td align="center">燃油/混动车型</td>
<td align="center">中高端</td>
</tr>
<tr>
<td align="center">14</td>
<td align="center">五菱</td>
<td align="center">全新整车</td>
<td align="center">中国</td>
<td align="center">1985</td>
<td align="center">微型电动车</td>
<td align="center">经济型</td>
</tr>
<tr>
<td align="center">15</td>
<td align="center">固特异 (Goodyear)</td>
<td align="center">汽车装饰</td>
<td align="center">美国</td>
<td align="center">1898</td>
<td align="center">防水脚垫</td>
<td align="center">中端</td>
</tr>
</tbody></table>
<h2 id="库表设计"><a href="#库表设计" class="headerlink" title="库表设计"></a>库表设计</h2><blockquote>
<p>2025 年 2 月 28 日</p>
</blockquote>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 产品分类</span><br><span class="hljs-comment">-- auto-generated definition</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_product_category<br>(<br>    id            <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key,<br>    parent_id     <span class="hljs-type">bigint</span>       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;一级分类编号(0表示一级分类)&#x27;</span>,<br>    name          <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;分类名称&#x27;</span>,<br>    level         <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;分类级别(0 - 1级 1 - 2级)&#x27;</span>,<br>    product_count <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品数量&#x27;</span>,<br>    product_unit  <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品数量单位&#x27;</span>,<br>    nav_status    <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;是否显示在导航栏：0-&gt;不显示；1-&gt;显示&#x27;</span>,<br>    show_status   <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;显示状态：0-&gt;不显示；1-&gt;显示&#x27;</span>,<br>    sort          <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;排序字段&#x27;</span>,<br>    icon          <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;图标&#x27;</span>,<br>    keywords      <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;关键词&#x27;</span>,<br>    description   text         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;分类描述&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;产品分类&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                       row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 品牌表</span><br><span class="hljs-comment">-- auto-generated definition</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_brand<br>(<br>    id                    <span class="hljs-type">bigint</span> auto_increment comment <span class="hljs-string">&#x27;id&#x27;</span><br>        <span class="hljs-keyword">primary</span> key,<br>    name                  <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;品牌名称&#x27;</span>,<br>    first_letter          <span class="hljs-type">varchar</span>(<span class="hljs-number">8</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;首字母&#x27;</span>,<br>    sort                  <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;排序字段&#x27;</span>,<br>    factory_status        <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;是否为品牌制造商(0 - 不是 1-是)&#x27;</span>,<br>    show_status           <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span>,<br>    product_count         <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;产品数量&#x27;</span>,<br>    product_comment_count <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;产品评论数量&#x27;</span>,<br>    logo                  <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;品牌logo&#x27;</span>,<br>    big_pic               <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;专区大图&#x27;</span>,<br>    brand_story           text         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;品牌故事&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;品牌表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                     row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 商品信息</span><br><span class="hljs-comment">-- auto-generated definition</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_product<br>(<br>    id                            <span class="hljs-type">bigint</span> auto_increment comment <span class="hljs-string">&#x27;id&#x27;</span><br>        <span class="hljs-keyword">primary</span> key,<br>    brand_id                      <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;品牌id&#x27;</span>,<br>    product_category_id           <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品分类&#x27;</span>,<br>    feight_template_id            <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span>,<br>    product_attribute_category_id <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;属性分类id&#x27;</span>,<br>    name                          <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>)   <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品名称&#x27;</span>,<br>    pic                           <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品样图&#x27;</span>,<br>    product_sn                    <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)    <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;货号&#x27;</span>,<br>    delete_status                 <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;删除状态(0 - 未删除；1 - 已删除)&#x27;</span>,<br>    publish_status                <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;上架状态(0 - 下架；1 - 上架)&#x27;</span>,<br>    new_status                    <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;新品状态(0 - 不是新品；1 - 新品)&#x27;</span>,<br>    recommand_status              <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;推荐状态(0 - 不推荐；1 - 推荐)&#x27;</span>,<br>    verify_status                 <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;审核状态：0-&gt;未审核；1-&gt;审核通过&#x27;</span>,<br>    sort                          <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;排序&#x27;</span>,<br>    sale                          <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;销量&#x27;</span>,<br>    price                         <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;销售价格&#x27;</span>,<br>    promotion_price               <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;促销价格&#x27;</span>,<br>    gift_growth                   <span class="hljs-type">int</span> <span class="hljs-keyword">default</span> <span class="hljs-number">0</span>  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;赠送的成长值&#x27;</span>,<br>    gift_point                    <span class="hljs-type">int</span> <span class="hljs-keyword">default</span> <span class="hljs-number">0</span>  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;赠送的积分&#x27;</span>,<br>    use_point_limit               <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;限制使用的积分数&#x27;</span>,<br>    sub_title                     <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;副标题&#x27;</span>,<br>    description                   text           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品描述&#x27;</span>,<br>    original_price                <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;市场价&#x27;</span>,<br>    stock                         <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;库存&#x27;</span>,<br>    low_stock                     <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;库存预警值&#x27;</span>,<br>    unit                          <span class="hljs-type">varchar</span>(<span class="hljs-number">16</span>)    <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;单位&#x27;</span>,<br>    weight                        <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品重量，默认为克&#x27;</span>,<br>    preview_status                <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;是否为预告商品：0-&gt;不是；1-&gt;是&#x27;</span>,<br>    service_ids                   <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)    <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;以逗号分割的产品服务：1-&gt;无忧退货；2-&gt;快速退款；3-&gt;免费包邮&#x27;</span>,<br>    keywords                      <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span>,<br>    note                          <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span>,<br>    album_pics                    <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;画册图片，连产品图片限制为5张，以逗号分割&#x27;</span>,<br>    detail_title                  <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span>,<br>    detail_desc                   text           <span class="hljs-keyword">null</span>,<br>    detail_html                   text           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;产品详情网页内容&#x27;</span>,<br>    detail_mobile_html            text           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;移动端网页详情&#x27;</span>,<br>    promotion_start_time          datetime       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;促销开始时间&#x27;</span>,<br>    promotion_end_time            datetime       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;促销结束时间&#x27;</span>,<br>    promotion_per_limit           <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;活动限购数量&#x27;</span>,<br>    promotion_type                <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;促销类型：0-&gt;没有促销使用原价;1-&gt;使用促销价；2-&gt;使用会员价；3-&gt;使用阶梯价格；4-&gt;使用满减价格；5-&gt;限时购&#x27;</span>,<br>    brand_name                    <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;品牌名称&#x27;</span>,<br>    product_category_name         <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品分类名称&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;商品信息&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                       row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<p>商品列表，商品分类，品牌列表，基本梳理完毕；商品属性，商品属性分类，商品属性值，待处理。</p>
<blockquote>
<p>2025 年 3 月 5 日</p>
</blockquote>
<p>完善系统流程图，接下来应该是代码开发环节。</p>
<p>表结构优先处理，十五张表应该是合适的，最多二十张表吧。</p>
<ul>
<li>pms_*：商品模块相关表</li>
<li>oms_*：订单模块相关表</li>
<li>sms_*：营销模块相关表</li>
<li>ums_*：权限模块相关表</li>
<li>cms_*：内容模块相关表</li>
</ul>
<p>商品模块相关表：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs">相册表，画册图片表，品牌表，商品评价表，商品评价回复表，运费模板表，商品会员价格表，<br>商品信息表，商品分类表，商品属性表，商品属性分类表，商品属性参数表，商品分类和商品属性关系表，<br>商品满减表，商品阶梯价格表，商品操作日志表，商品审核记录表，商品库存表，<br></code></pre></td></tr></table></figure>

<p>品牌表，商品信息表，商品分类表，商品属性表，商品属性分类表，商品属性参数表，商品库存表，商品满减表，商品评价表，商品评价回复表。</p>
<p>订单模块相关表：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">购物车表，公司收发货地址表，订单表，订单商品信息表，订单操作历史记录表，订单退货申请表，退货原因表，设置表，<br></code></pre></td></tr></table></figure>

<p>购物车表，公司收发货地址表，订单表，订单退货申请表。</p>
<p>内容模块相关表：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs">帮助表，帮助分类表，用户举报表，<br>优选专区表，优选专区和产品关系表，<br>专题表，专题分类表，专题评论表，专题商品关系表，<br>话题表，话题分类表，话题评论表，<br></code></pre></td></tr></table></figure>

<p>用户反馈表。</p>
<p>营销模块相关表：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs">优惠券表，优惠券领取使用记录表，优惠券和产品关系表，优惠券和产品分类关系表，<br>限时购表，限时购通知表，限时购与商品关系表，限时购场次表，<br>首页轮播广告表，首页推荐商品表，新鲜好物商品表，人气推荐商品表，首页推荐专题表，<br></code></pre></td></tr></table></figure>

<p>优惠券表，优惠券领取使用表，首页轮播广告表，促销活动通知表。</p>
<p>权限模块相关表：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">后台用户表，后台用户登录日志表，后台用户和权限关系表，后台用户和角色关系表，成长值变化历史记录表，积分变化历史记录表，积分消费设置表，会员表，会员登记表，会员登录记录表，用户和标签关系表，会员和商品分类关系表，会员收货地址表，会员积分成长规则表，会员统计信息表，用户标签表，会员任务表，后台菜单表，后台用户权限表，后台资源表，资源分类表，后台用户角色表，后台用户角色和菜单关系表，后台用户角色和权限关系表，后台用户角色资源关系表。<br></code></pre></td></tr></table></figure>

<p>用户表，用户角色表。</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs pgsql"><span class="hljs-comment">-- 品牌表</span><br><span class="hljs-comment">-- auto-generated definition</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_brand<br>(<br>    id                    <span class="hljs-type">bigint</span> auto_increment <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;id&#x27;</span><br>        <span class="hljs-keyword">primary key</span>,<br>    <span class="hljs-type">name</span>                  <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">null</span> <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;品牌名称&#x27;</span>,<br>    first_letter          <span class="hljs-type">varchar</span>(<span class="hljs-number">8</span>)   <span class="hljs-keyword">null</span> <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;首字母&#x27;</span>,<br>    sort                  <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;排序字段&#x27;</span>,<br>    factory_status        <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;是否为品牌制造商(0 - 不是 1-是)&#x27;</span>,<br>    show_status           <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span>,<br>    product_count         <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;产品数量&#x27;</span>,<br>    product_comment_count <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;产品评论数量&#x27;</span>,<br>    logo                  <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">null</span> <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;品牌logo&#x27;</span>,<br>    big_pic               <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">null</span> <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;专区大图&#x27;</span>,<br>    brand_story           <span class="hljs-type">text</span>         <span class="hljs-keyword">null</span> <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;品牌故事&#x27;</span><br>)<br>    <span class="hljs-keyword">comment</span> <span class="hljs-string">&#x27;品牌表&#x27;</span> charset = utf8<br>                     row_format = DYNAMIC;<br></code></pre></td></tr></table></figure>

<p>大概二十一张表。</p>
<blockquote>
<p>2025 年 3 月 5 日</p>
</blockquote>
<p><strong>商品模块相关表</strong>：品牌表，商品信息表，商品分类表，商品属性表，商品属性分类表，商品属性值表，商品满减表，商品评价表，商品评价回复表。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 品牌表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_brand<br>(<br>    id                    <span class="hljs-type">bigint</span> auto_increment comment <span class="hljs-string">&#x27;id&#x27;</span><br>        <span class="hljs-keyword">primary</span> key,<br>    name                  <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;品牌名称&#x27;</span>,<br>    first_letter          <span class="hljs-type">varchar</span>(<span class="hljs-number">8</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;首字母&#x27;</span>,<br>    product_count         <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;产品数量&#x27;</span>,<br>    logo                  <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;品牌logo&#x27;</span>,<br>    brand_story           text         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;品牌故事&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;品牌表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                     row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 商品信息表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_product<br>(<br>    id                            <span class="hljs-type">bigint</span> auto_increment comment <span class="hljs-string">&#x27;id&#x27;</span><br>        <span class="hljs-keyword">primary</span> key,<br>    name                          <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>)   <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品名称&#x27;</span>,<br>    description                   text           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品描述&#x27;</span>,<br>    brand_id                      <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属品牌&#x27;</span>,<br>    product_category_id           <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属分类&#x27;</span>,<br>    product_attribute_category_id <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属属性分类&#x27;</span>,<br>    pic                           <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品样图&#x27;</span>,<br>    publish_status                <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;上架状态(0 - 下架；1 - 上架)&#x27;</span>,<br>    sale                          <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;销量&#x27;</span>,<br>    price                         <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;销售价格&#x27;</span>,<br>    promotion_price               <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;促销价格&#x27;</span>,<br>    promotion_type                <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;促销类型：0-&gt;使用原价;1-&gt;使用满减价格；2-&gt;使用促销价；4-&gt;限时购&#x27;</span>,<br>    stock                         <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;库存&#x27;</span>,<br>    low_stock                     <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;库存预警值&#x27;</span>,<br>    weight                        <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品重量，默认为克&#x27;</span>,<br>)<br>    comment <span class="hljs-string">&#x27;商品信息表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                       row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 商品分类表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_product_category<br>(<br>    id            <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key,<br>    name          <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;分类名称&#x27;</span>,<br>    description   text         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;描述&#x27;</span>,<br>    parent_id     <span class="hljs-type">bigint</span>       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;上级分类级别(0表示一级分类)&#x27;</span>,<br>    level         <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属分类级别(0 - 1级 1 - 2级)&#x27;</span>,<br>    product_count <span class="hljs-type">int</span>          <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品数量&#x27;</span>,<br>    product_unit  <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品数量单位&#x27;</span>,<br>    icon          <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;图标&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;商品分类表 &#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                       row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 商品属性表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_product_attribute<br>(<br>    id                            <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key,<br>    name                          <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;属性名称&#x27;</span>,<br>    product_attribute_category_id <span class="hljs-type">bigint</span>       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属分类&#x27;</span>,<br>    select_type                   <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;选择类型：0-&gt;唯一；1-&gt;单选；2-&gt;多选&#x27;</span>,<br>    input_list                    <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;可选列表，以逗号隔开&#x27;</span>,<br>    type                          <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;属性类型；0-&gt;规格；1-&gt;参数&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;商品属性参数表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                             row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 商品属性分类表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_product_attribute_category<br>(<br>    id              <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key,<br>    name            <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;属性分类名&#x27;</span>,<br>    attribute_count <span class="hljs-type">int</span> <span class="hljs-keyword">default</span> <span class="hljs-number">0</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;包含值数量&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;商品属性分类表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                             row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 商品属性值表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_product_attribute_value<br>(<br>    id                   <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key,<br>    product_id           <span class="hljs-type">bigint</span>      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属商品&#x27;</span>,<br>    product_attribute_id <span class="hljs-type">bigint</span>      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属属性&#x27;</span>,<br>    <span class="hljs-keyword">value</span>                <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;参数值&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;商品属性值表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                                   row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 商品评价表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_comment<br>(<br>    id                <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key,<br>    product_id        <span class="hljs-type">bigint</span>        <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属商品&#x27;</span>,<br>    member_id         <span class="hljs-type">bigint</span>  	    <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属用户&#x27;</span>,<br>    content           text          <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;评价内容&#x27;</span>,<br>    pics              <span class="hljs-type">varchar</span>(<span class="hljs-number">1000</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;上传图片地址，以逗号隔开&#x27;</span>,<br>    create_time       datetime      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;评价时间&#x27;</span>,<br>    star              <span class="hljs-type">int</span>(<span class="hljs-number">3</span>)        <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;评价星数：0-&gt;5&#x27;</span>,<br>    collect_counnt    <span class="hljs-type">int</span>           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;点赞数量&#x27;</span>,<br>    read_count        <span class="hljs-type">int</span>           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;阅读数量&#x27;</span>,<br>    replay_count      <span class="hljs-type">int</span>           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;回复数量&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;商品评价表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                         row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 评价回复表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_comment_replay<br>(<br>    id               <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key,<br>    comment_id       <span class="hljs-type">bigint</span>        <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属评论&#x27;</span>,<br>    member_id        <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属用户&#x27;</span>,<br>    content          <span class="hljs-type">varchar</span>(<span class="hljs-number">1000</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;回复内容&#x27;</span>,<br>    create_time      datetime      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;回复时间&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;评价回复表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                             row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 商品满减表(只针对同商品)</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_product_full_reduction<br>(<br>    id           <span class="hljs-type">bigint</span>(<span class="hljs-number">11</span>) auto_increment<br>        <span class="hljs-keyword">primary</span> key,<br>    product_id   <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属商品&#x27;</span>,<br>    full_price   <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;满减金额&#x27;</span>,<br>    reduce_price <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;减少金额&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;商品满减表(只针对同商品)&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                                       row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<p><strong>订单模块相关表</strong>：购物车表，公司收发货地址表，订单表，订单退货申请表。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 购物车表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> oms_cart_item<br>(<br>    id                  <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key comment <span class="hljs-string">&#x27;id&#x27;</span>,<br>    product_id          <span class="hljs-type">bigint</span>           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;购买商品&#x27;</span>,<br>    member_id           <span class="hljs-type">bigint</span>           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;购买用户&#x27;</span>,<br>    quantity            <span class="hljs-type">int</span>              <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;购买数量&#x27;</span>,<br>    price               <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;需付金额&#x27;</span>,<br>    price_reduce        <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;实付金额&#x27;</span>,<br>    product_pic         <span class="hljs-type">varchar</span>(<span class="hljs-number">1000</span>)    <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品主图&#x27;</span>,<br>    create_date         datetime         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;创建时间&#x27;</span>,<br>    modify_date         datetime         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;修改时间&#x27;</span>,<br>    delete_status       <span class="hljs-type">int</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-number">0</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;是否删除&#x27;</span>,<br>    product_category_id <span class="hljs-type">bigint</span>           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属分类&#x27;</span>,<br>    product_brand       <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>)     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属品牌&#x27;</span>,<br>    product_attr_id     <span class="hljs-type">varchar</span>(<span class="hljs-number">500</span>)     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属商品属性&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;购物车表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                       row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 订单表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> oms_order<br>(<br>    id                      <span class="hljs-type">bigint</span> auto_increment comment <span class="hljs-string">&#x27;id&#x27;</span><br>        <span class="hljs-keyword">primary</span> key,<br>    member_id               <span class="hljs-type">bigint</span>           <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;下单用户&#x27;</span>,<br>    payment_time            datetime         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;支付时间&#x27;</span>,<br>    pay_amount              <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;实支金额&#x27;</span>,<br>    freight_amount          <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;运费金额&#x27;</span>,<br>    total_amount            <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;订单总金额&#x27;</span>,<br>    promotion_amount        <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;促销优化金额（促销价、满减）&#x27;</span>,<br>    coupon_amount           <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;优惠券抵扣金额&#x27;</span>,<br>    pay_type                <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;支付方式：0-&gt;未支付；1-&gt;支付宝；2-&gt;微信&#x27;</span>,<br>    status                  <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;订单状态：0-&gt;待付款；1-&gt;待发货；2-&gt;已发货；3-&gt;已完成；4-&gt;已关闭；5-&gt;无效订单&#x27;</span>,<br>    receiver_name           <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>)     <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;收货人姓名&#x27;</span>,<br>    receiver_phone          <span class="hljs-type">varchar</span>(<span class="hljs-number">32</span>)      <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;收货人电话&#x27;</span>,<br>    note                    <span class="hljs-type">varchar</span>(<span class="hljs-number">500</span>)     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;订单备注&#x27;</span>,<br>    delivery_company        <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;物流公司(配送方式)&#x27;</span>,<br>    delivery_sn             <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;物流单号&#x27;</span>,<br>    receiver_detail_address <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>)     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;收货详细地址&#x27;</span>,<br>    confirm_status          <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;确认收货状态：0-&gt;未确认；1-&gt;已确认&#x27;</span>,<br>    delivery_time           datetime         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;发货时间&#x27;</span>,<br>)<br>    comment <span class="hljs-string">&#x27;订单表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                     row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 退货申请</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> oms_order_return_apply<br>(<br>    id                 <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key comment <span class="hljs-string">&#x27;id&#x27;</span>,<br>    order_id           <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;订单id&#x27;</span>,<br>    company_address_id <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;收货地址&#x27;</span>,<br>    product_id         <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;退货商品&#x27;</span>,<br>    create_time        datetime       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;申请时间&#x27;</span>,<br>    return_amount      <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;退款金额&#x27;</span>,<br>    return_name        <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;退货人姓名&#x27;</span>,<br>    return_phone       <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;退货人电话&#x27;</span>,<br>    status             <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;申请状态：0-&gt;待处理；1-&gt;退货中；2-&gt;已完成；3-&gt;已拒绝&#x27;</span>,<br>    handle_time        datetime       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;处理时间&#x27;</span>,<br>    product_count      <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;退货数量&#x27;</span>,<br>    reason             <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;退货原因&#x27;</span>,<br>    proof_pics         <span class="hljs-type">varchar</span>(<span class="hljs-number">1000</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;凭证图片，以逗号隔开&#x27;</span>,<br>    handle_note        <span class="hljs-type">varchar</span>(<span class="hljs-number">500</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;处理备注&#x27;</span>,<br>    handle_man         <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;处理人员&#x27;</span>,<br>)<br>    comment <span class="hljs-string">&#x27;退货申请&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                           row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<p><strong>内容模块相关表</strong>：用户反馈表。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 用户反馈表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> cms_member_report<br>(<br>    id                 <span class="hljs-type">bigint</span>       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;id&#x27;</span>,<br>    report_member_id   <span class="hljs-type">bigint</span>       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;反馈人&#x27;</span>,<br>    report_content     <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;反馈内容&#x27;</span>,<br>    report_type        <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;反馈类型：0-&gt;商品信息；1-&gt;活动内容；2-&gt;用户评价&#x27;</span>,<br>    report_status      <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;反馈状态：0-&gt;未处理；1-&gt;已处理&#x27;</span>,<br>    handle_status      <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;处理结果：0-&gt;无效；1-&gt;有效；2-&gt;恶意&#x27;</span>,<br>)<br>    comment <span class="hljs-string">&#x27;用户反馈表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                         row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span><br></code></pre></td></tr></table></figure>

<p><strong>营销模块相关表</strong>：优惠券表，优惠券领取使用表，首页轮播广告表，促销活动通知表。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 优惠券表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> sms_coupon<br>(<br>    id            <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key comment <span class="hljs-string">&#x27;id&#x27;</span>,<br>    type          <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所属类型；0-&gt;注册赠券；1-&gt;购物赠券；2-&gt;店铺赠券；3-&gt;全场赠券；&#x27;</span>,<br>    name          <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;名称&#x27;</span>,<br>    count         <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;数量&#x27;</span>,<br>    amount        <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;金额&#x27;</span>,<br>    per_limit     <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;每人限领张数&#x27;</span>,<br>    min_point     <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;使用门槛；0表示无门槛&#x27;</span>,<br>    start_time    datetime       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;有效时间&#x27;</span>,<br>    end_time      datetime       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;失效时间&#x27;</span>,<br>    note          <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;备注&#x27;</span>,<br>    enable_time   datetime       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;可领取日期&#x27;</span>,<br>    publish_count <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;发行数量&#x27;</span>,<br>    receive_count <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;已领取数量&#x27;</span>,<br>)<br>    comment <span class="hljs-string">&#x27;优惠券表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                       row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 促销活动表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> sms_flash_promotion<br>(<br>    id          <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key comment <span class="hljs-string">&#x27;id&#x27;</span>,<br>    title       <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;活动名称&#x27;</span>,<br>    start_date  <span class="hljs-type">date</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;开始日期&#x27;</span>,<br>    end_date    <span class="hljs-type">date</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;结束日期&#x27;</span>,<br>    status      <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;上下线状态&#x27;</span>,<br>    create_time datetime     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;创建时间&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;促销活动表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                       row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span><br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 轮播广告表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> sms_home_advertise<br>(<br>    id          <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key comment <span class="hljs-string">&#x27;id&#x27;</span>,<br>    name        <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;广告名称&#x27;</span>,<br>    pic         <span class="hljs-type">varchar</span>(<span class="hljs-number">500</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;轮播图片&#x27;</span>,<br>    start_time  datetime      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;开始时间&#x27;</span>,<br>    end_time    datetime      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;结束时间&#x27;</span>,<br>    status      <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)        <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;上下线状态：0-&gt;下线；1-&gt;上线&#x27;</span>,<br>)<br>    comment <span class="hljs-string">&#x27;轮播广告表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                             row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<p><strong>权限模块相关表</strong>：后台用户表，注册用户表，用户角色表。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 后台用户表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> ums_admin<br>(<br>    id          <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key comment <span class="hljs-string">&#x27;id&#x27;</span><br>    user_name   <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;账号名&#x27;</span>,<br>    password    <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;密码&#x27;</span>,<br>    icon        <span class="hljs-type">varchar</span>(<span class="hljs-number">500</span>)     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;头像&#x27;</span>,<br>    email       <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>)     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;邮箱&#x27;</span>,<br>    note        <span class="hljs-type">varchar</span>(<span class="hljs-number">500</span>)     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;备注信息&#x27;</span>,<br>    user_role	<span class="hljs-type">int</span>(<span class="hljs-number">1</span>)			<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;用户角色&#x27;</span>,<br>    create_time datetime         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;创建时间&#x27;</span>,<br>    login_time  datetime         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;最后登录时间&#x27;</span>,<br>    status      <span class="hljs-type">int</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-number">1</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;帐号启用状态：0-&gt;禁用；1-&gt;启用&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;后台用户表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                         row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span><br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 注册用户表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> ums_member<br>(<br>    id                     <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key comment <span class="hljs-string">&#x27;id&#x27;</span>,<br>    user_name               <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;用户名&#x27;</span>,<br>    password               <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>) 		<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;密码&#x27;</span>,<br>    nickname               <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;昵称&#x27;</span>,<br>    user_role			  <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)			<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;用户角色&#x27;</span>,<br>    phone                  <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;手机号码&#x27;</span>,<br>    email       		  <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>)      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;邮箱&#x27;</span>,<br>    status                 <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;帐号启用状态:0-&gt;禁用；1-&gt;启用&#x27;</span>,<br>    icon                   <span class="hljs-type">varchar</span>(<span class="hljs-number">500</span>) 	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;头像&#x27;</span>,<br>    gender                 <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)       	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;性别：0-&gt;未知；1-&gt;男；2-&gt;女&#x27;</span>,<br>    birthday               <span class="hljs-type">date</span>         	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;生日&#x27;</span>,<br>    city                   <span class="hljs-type">varchar</span>(<span class="hljs-number">64</span>)  	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;所在城市&#x27;</span>,<br>    job                    <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>) 	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;职业&#x27;</span>,<br>    personalized_signature <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>) 	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;个性签名&#x27;</span>,<br>    create_time            datetime     	<span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;注册时间&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;注册用户表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                     row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 用户角色表</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> ums_role<br>(<br>    id          <span class="hljs-type">bigint</span> auto_increment<br>        <span class="hljs-keyword">primary</span> key comment <span class="hljs-string">&#x27;id&#x27;</span>,<br>    name        <span class="hljs-type">varchar</span>(<span class="hljs-number">100</span>)     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;角色名称&#x27;</span>,<br>    description <span class="hljs-type">varchar</span>(<span class="hljs-number">500</span>)     <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;角色描述&#x27;</span>,<br>    count 	    <span class="hljs-type">int</span>              <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;包含用户数量&#x27;</span>,<br>    create_time datetime         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;创建时间&#x27;</span>,<br>    status      <span class="hljs-type">int</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">default</span> <span class="hljs-number">1</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;启用状态：0-&gt;禁用；1-&gt;启用&#x27;</span>,<br>)<br>    comment <span class="hljs-string">&#x27;后台用户角色表&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                             row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<p>好极了，目前缩减至十九张表。</p>
<blockquote>
<p>2025 年 3 月 6 日</p>
</blockquote>
<p>历时两天，完成数据库概念设计和数据库逻辑设计。</p>
<h2 id="功能结构"><a href="#功能结构" class="headerlink" title="功能结构"></a>功能结构</h2><blockquote>
<p>2025 年 3 月 3 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.macrozheng.com/">项目主页 | mall 学习教程 (macrozheng.com)</a></p>
<p>功能需求分析，前台功能和后台功能。</p>
<p>角色用例分析，管理员角色用例和普通用户角色用例。</p>
<p>系统功能结构设计，前台功能结构设计和后台功能结构设计。</p>
<p>系统流程分析，从注册登录，到检索选择自己想要的商品，完善收获地址信息下单后添加进购物车，最终支付订单的整个流程。</p>
<p>这块儿详细写两个流程分析，用户登录注册，以及购买商品的整个流程。</p>
<p>系统流程图，数据库设计，数据库概念设计和逻辑设计。</p>
<p>系统实现，后台登录模块和后台管理模块，前台登录模块和前台使用模块。</p>
<p>系统测试，网站登录测试，选购商品测试，支付下单测试。</p>
<p>基本就是以上几点内容。针对每一条再做细节优化和内容填充。</p>
<hr>
<p><strong>功能需求分析。</strong></p>
<p>前台功能：<strong>首页智能推荐</strong>，<strong>商品详情展示</strong>，<strong>购物下单功能</strong>，<strong>活动精准推送</strong>，<strong>我的个人空间</strong>。</p>
<p>后台功能：商品管理功能，订单管理功能，营销管理功能，权限管理功能和用户管理功能。</p>
<p><strong>前台功能通俗版</strong></p>
<ol>
<li><strong>首页猜你喜欢</strong><ul>
<li>轮播大图推爆款 | 品牌直营专区 | 新人必买清单 | 根据浏览记录智能推荐</li>
</ul>
</li>
<li><strong>商品详情百科</strong><ul>
<li>分类找货更方便 | 商品图文详情页（参数对比一目了然） | 秒杀/新品专属福利区</li>
</ul>
</li>
<li><strong>从购物车到付款</strong><ul>
<li>加购商品随时改 | 自动计算优惠价 | 多支付方式一键下单 | 物流实时追踪</li>
</ul>
</li>
<li><strong>活动精准推送</strong><ul>
<li>节日大促专题页（如 618/双 11） | 限时抢购倒计时 | 猜你喜欢个性化推荐</li>
</ul>
</li>
<li><strong>我的个人空间</strong><ul>
<li>优惠券/收藏夹管理 | 收货地址簿 | 浏览足迹回溯 | 商品评价记录</li>
</ul>
</li>
</ol>
<p><strong>角色用例分析。</strong></p>
<p>管理员角色用例：商品管理，订单管理，促销管理，运营管理，权限管理，用户管理，内容管理，统计报表，财务管理。</p>
<p>普通用户角色用例：登录和注册，修改个人资料，查看促销活动，查看优惠券，浏览商品，浏览详情页，查看账户余额，添加购物车，多方式支付下单，查看我的订单。</p>
<p><strong>系统功能结构设计。</strong></p>
<p>系统前台功能：登录，注册，个人中心，首页门户，商品推荐，商品搜索，商品展示，购物车，订单流程，帮助中心，客户服务。</p>
<p>系统后台功能：商品管理，订单管理，促销管理，运营管理，权限管理，用户管理，内容管理，财务管理。</p>
<p><strong>系统流程分析。</strong></p>
<p>本系统涉及到的主要流程有：用户登录注册，浏览选购，选择规格加购，支付订单，收货评价。</p>
<p>登录注册流程：</p>
<p>用户下单流程：<strong>用户选择商品</strong>，<strong>检查库存</strong>，<strong>确认订单信息</strong>，<strong>支付订单</strong>。</p>
<p><strong>本系统主要流程如下</strong>：</p>
<ol>
<li><strong>注册/登录</strong><ul>
<li>新用户手机号一键注册，老用户支持微信/账号密码登录</li>
<li>_后台支撑_：用户权限管理、登录日志风控（防刷号）</li>
</ul>
</li>
<li><strong>浏览选购</strong><ul>
<li>首页搜商品（关键词搜索/分类导航）、看详情页（参数对比/买家秀）</li>
<li>_后台支撑_：商品分类管理、库存状态实时同步</li>
</ul>
</li>
<li><strong>选规格加购</strong><ul>
<li>选择颜色/尺寸/套餐，加入购物车或直接购买</li>
<li>_后台支撑_：SKU 库存动态扣减、购物车有效期设置</li>
</ul>
</li>
<li><strong>支付订单</strong><ul>
<li>合并购物车商品，选择优惠券抵扣，微信/支付宝/银行卡支付</li>
<li>_后台支撑_：订单状态流转（待付款 → 已支付）、支付流水对账</li>
</ul>
</li>
<li><strong>收货评价</strong><ul>
<li>查看物流轨迹，确认收货后发表带图评价</li>
<li>_后台支撑_：物流接口对接、评价内容审核</li>
</ul>
</li>
</ol>
<p><strong>用户购物下单流程</strong></p>
<ol>
<li><strong>用户选择商品</strong><ul>
<li>用户在商城浏览商品，根据喜好选择商品型号（如颜色、尺寸等）。</li>
</ul>
</li>
<li><strong>检查库存</strong><ul>
<li>如果商品库存充足，用户可以加入购物车或立即购买；如果库存不足，则提示“库存不足，无法购买”。</li>
</ul>
</li>
<li><strong>确认订单信息</strong><ul>
<li>用户点击“立即购买”后，进入订单确认页面，显示商品信息、总金额、优惠券抵扣及支付方式（如余额支付、微信支付等）。</li>
</ul>
</li>
<li><strong>支付订单</strong><ul>
<li>用户点击“支付”后：<ul>
<li>若支付成功（余额充足或第三方支付成功），订单生成，库存扣减，用户收到订单成功通知；</li>
<li>若支付失败（余额不足或支付超时），订单取消，返回支付页面重新操作。</li>
</ul>
</li>
</ul>
</li>
</ol>
<p><strong>系统流程图。</strong></p>
<p><strong>数据库设计，数据库概念设计和逻辑设计。</strong></p>
<p><strong>系统测试，网站登录测试，选购商品测试，下单支付测试。</strong></p>
<p>剩下的这三块核心内容今天先暂时不做补充，补充前三章内容先。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/Tir_zhang/article/details/135428037">【毕业设计】– 如何使用 Visio 画系统功能结构图_系统功能模块图怎么画-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://jingyan.baidu.com/article/a3f121e4bbed7afc9052bbf6.html">毕业论文中的系统总体设计流程图如何画-百度经验 (baidu.com)</a></p>
<h2 id="系统流程"><a href="#系统流程" class="headerlink" title="系统流程"></a>系统流程</h2><blockquote>
<p>2025 年 3 月 4 日</p>
</blockquote>
<p>完成系统流程图。</p>
<h2 id="系统实现"><a href="#系统实现" class="headerlink" title="系统实现"></a>系统实现</h2><blockquote>
<p>2025 年 3 月 7 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.macrozheng.com/">项目主页 | mall 学习教程 (macrozheng.com)</a></p>
<p><strong>后台功能模块</strong></p>
<p>后台登录模块：</p>
<p>后台管理模块：</p>
<p><strong>前台功能模块</strong></p>
<p>前台登录模块：</p>
<p>前台使用模块：</p>
<blockquote>
<p>2025 年 4 月 1 日</p>
</blockquote>
<p>自从半个多月前中期答辩结束后，再没有关注论文和毕设，今天估摸着工作量，只有修改数据库。</p>
<p>数据库商品品牌，对应商品信息，规格，这些都要一个个调整，前端页面展示才算正常。</p>
<p>好无聊的工作。</p>
<blockquote>
<p>2025 年 4 月 2 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.baidu.com/s?wd=%E7%9B%AF%E7%9B%AF%E6%8B%8D%E4%BB%B7%E6%A0%BC&tn=15007414_23_dg&ie=utf-8">盯盯拍价格_百度搜索 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&dyTabStr=MCwxMiwzLDEsMiwxMyw3LDYsNSw5&word=%E7%9B%AF%E7%9B%AF%E6%8B%8D%E4%BF%83%E9%94%80%E5%B9%BF%E5%91%8A">盯盯拍促销广告_百度图片搜索 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&dyTabStr=MCwxMiwzLDEsMiwxMyw3LDYsNSw5&word=%E6%B1%BD%E9%85%8D%E9%94%80%E5%94%AE%E5%B9%BF%E5%91%8A%E6%B5%B7%E6%8A%A5">汽配销售广告海报_百度图片搜索 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&dyTabStr=MCwxMiwzLDEsMiwxMyw3LDYsNSw5&word=%E7%89%B9%E6%96%AF%E6%8B%89">特斯拉_百度图片搜索 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_BYSJ1987/article/details/141563388">基于 Java Web 的汽车销售管理系统的设计与实现—附源码 97848_基于 web 的汽车销售信息管理系统设计与实现-CSDN 博客</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250402212144516.png" alt="image-20250402212144516"></p>
<p>十点二十分了，搞了五个多小时。</p>
<blockquote>
<p>2025 年 4 月 10 日</p>
</blockquote>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs makefile">@所有人，请注意：目前我在修改论文中发现的共性问题<br>1.相关技术：挑选3-4个系统用到的核心技术介绍，尽量用自己的语句描述，不能照搬AI，这一部分容易造成较高的查重率<br><span class="hljs-section">说明:这一部分不是必要的，根据自己的系统实际情况设置</span><br>2.需求分析：需要补充系统整体用例图，大部分同学都是按角色单独罗列的！！！<br>例如：参考以下这篇论文中3.1节的系统整体用例图用<br><span class="hljs-section">3.系统总体设计:包含系统架构设计、功能结构设计、类设计（指系统整体类设计）</span><br>4.系统详细设计：需包含系统核心功能模块（至少3个）的类的详细设计、数据库设计（包括E-R模型和主要数据库表设计）<br><span class="hljs-section">说明:系统总体设计和详细设计中，大部分同学都没有关于类的设计，需要补充类设计！！！</span><br>例如：参考以下这篇论文中4.1节架构设计、4.4节的系统类设计、5.1节中核心功能类的详细设计<br><span class="hljs-section">5.系统实现:包含系统核心功能模块的详细实现（用顺序图表示）、数据库的连接、系统各个运行功能截图</span><br><span class="hljs-section">说明:大部分同学都没有用顺序图描述核心功能的实现，需要补充！！！</span><br>例如：参考以下这篇论文中5.1节中核心功能的顺序图如何实现<br>6.系统测试：包括测试目的和意义、测试用例（至少3个系统核心功能的）、测试结果<br>7.结论：1）本文用什么技术实现了系统的什么功能，即本文所做的工作的总结；2）对本系统存在的不足作总结及未来的计划的改进<br></code></pre></td></tr></table></figure>

<h3 id="用户登录实现"><a href="#用户登录实现" class="headerlink" title="用户登录实现"></a>用户登录实现</h3><blockquote>
<p>2025 年 4 月 11 日</p>
</blockquote>
<p>用户登录详细设计。</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pgsql">用户登录模块包含用户认证、权限验证和日志记录，涉及到的类有用户类（<span class="hljs-keyword">User</span>）、角色类（<span class="hljs-keyword">Role</span>）、权限类（Permission）和登录日志类（LoginLog）。用户类中除了基本的属性如username、<span class="hljs-keyword">password</span>和status外，还包含checkPassword方法用于验证用户输入的密码是否与存储的加密，isLocked方法用于检查账户是否被锁定，encryptPassword方法用于密码加密存储。角色类通过hasPermission方法验证用户是否拥有特定权限，addPermission方法用于动态添加权限。权限类通过isApiPermission方法判断权限类型，getFullPermissionCode方法生成完整的权限标识。登录日志类中的createSuccessLog静态方法用于快速创建成功登录日志记录，自动填充IP、设备和时间等信息。这些类通过关联关系协同工作，用户类关联多个角色类形成用户-角色关系，角色类关联多个权限类构成角色-权限映射，用户类与登录日志类形成一对多的登录记录关系，共同完成从用户认证到权限控制的完整流程。类详细设计如下。<br></code></pre></td></tr></table></figure>

<p>用户登录类关系图。</p>
<pre><code class=" mermaid">classDiagram
    %% 类定义
    class User &#123;
        -id: Long
        -username: String
        -password: String
        -status: Integer
        +checkPassword(inputPassword: String): boolean
        +isLocked(): boolean
        +encryptPassword(rawPassword: String): void
    &#125;

    class Role &#123;
        -id: Long
        -code: String
        -name: String
        +hasPermission(permissionCode: String): boolean
        +addPermission(permission: Permission): void
    &#125;

    class Permission &#123;
        -id: Long
        -code: String
        -resourceType: String
        +isApiPermission(): boolean
        +getFullPermissionCode(): String
    &#125;

    class LoginLog &#123;
        -id: Long
        -userId: Long
        -ip: String
        -device: String
        +createSuccessLog(user: User, request: HttpServletRequest): LoginLog
    &#125;

    %% 类关系
    User &quot;1&quot; *-- &quot;n&quot; Role : &quot;拥有&quot;
    Role &quot;1&quot; *-- &quot;n&quot; Permission : &quot;包含&quot;
    User &quot;1&quot; ..&gt; &quot;n&quot; LoginLog : &quot;生成&quot;
</code></pre>

<figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs armasm">用户登录模块中相关的数据库表包含用户表（sys_user）、角色表（sys_role）、权限表（sys_permission）、用户角色关联表（sys_user_role）、角色权限关联表（sys_role_permission）以及登录日志表（sys_login_log）。通过用户表中的用户状态字段与角色权限体系建立连接，在用户登录时进行多层级验证，包括密码校验、账户状态检查和权限加载。登录日志表记录了每次登录的详细上下文信息，包括<span class="hljs-built_in">IP</span>地址、设备类型和操作结果，这些数据通过用户ID与用户表关联。权限控制体系采用RBAC模型，用户通过角色关联权限，权限表中的权限编码字段与前端菜单及接口权限绑定，形成完整的访问控制链。数据库表结构中，用户表存储加密后的密码和盐值，角色表定义数据权限范围，权限表标记资源类型和操作标识，关联表维护多对多关系，登录日志表实现审计追踪，各表通过外键约束确保数据一致性，共同支撑从身份认证到权限管理的全流程。数据库表结构如下。<br></code></pre></td></tr></table></figure>

<p>数据库表结构。</p>
<p>表 5-1 后台用户表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>用户 ID</td>
</tr>
<tr>
<td>username</td>
<td>varchar(64)</td>
<td>N</td>
<td>N</td>
<td>登录账号（唯一）</td>
</tr>
<tr>
<td>password</td>
<td>varchar(128)</td>
<td>N</td>
<td>N</td>
<td>BCrypt 加密后的密码</td>
</tr>
<tr>
<td>salt</td>
<td>varchar(32)</td>
<td>N</td>
<td>N</td>
<td>加密盐值</td>
</tr>
<tr>
<td>phone</td>
<td>varchar(20)</td>
<td>N</td>
<td>Y</td>
<td>绑定手机号（唯一）</td>
</tr>
<tr>
<td>email</td>
<td>varchar(100)</td>
<td>N</td>
<td>Y</td>
<td>绑定邮箱（唯一）</td>
</tr>
<tr>
<td>avatar</td>
<td>varchar(255)</td>
<td>N</td>
<td>Y</td>
<td>头像 URL</td>
</tr>
<tr>
<td>status</td>
<td>tinyint(1)</td>
<td>N</td>
<td>N</td>
<td>状态（0-禁用，1-正常，2-锁定）</td>
</tr>
<tr>
<td>last_login_ip</td>
<td>varchar(50)</td>
<td>N</td>
<td>Y</td>
<td>最后登录 IP</td>
</tr>
<tr>
<td>last_login_time</td>
<td>datetime</td>
<td>N</td>
<td>Y</td>
<td>最后登录时间</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>创建时间</td>
</tr>
<tr>
<td>update_time</td>
<td>datetime</td>
<td>N</td>
<td>Y</td>
<td>更新时间</td>
</tr>
<tr>
<td>is_deleted</td>
<td>tinyint(1)</td>
<td>N</td>
<td>N</td>
<td>逻辑删除（0-未删，1-已删）</td>
</tr>
</tbody></table>
<p>表 5-2 角色表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>角色 ID</td>
</tr>
<tr>
<td>code</td>
<td>varchar(50)</td>
<td>N</td>
<td>N</td>
<td>角色编码（如 ROLE_ADMIN）</td>
</tr>
<tr>
<td>name</td>
<td>varchar(50)</td>
<td>N</td>
<td>N</td>
<td>角色名称</td>
</tr>
<tr>
<td>data_scope</td>
<td>tinyint(1)</td>
<td>N</td>
<td>Y</td>
<td>数据权限（0-全部，1-本部门）</td>
</tr>
<tr>
<td>description</td>
<td>varchar(200)</td>
<td>N</td>
<td>Y</td>
<td>描述</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>创建时间</td>
</tr>
<tr>
<td>update_time</td>
<td>datetime</td>
<td>N</td>
<td>Y</td>
<td>更新时间</td>
</tr>
<tr>
<td>is_deleted</td>
<td>tinyint(1)</td>
<td>N</td>
<td>N</td>
<td>逻辑删除</td>
</tr>
</tbody></table>
<p>表 5-3 权限表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>权限 ID</td>
</tr>
<tr>
<td>code</td>
<td>varchar(100)</td>
<td>N</td>
<td>N</td>
<td>权限码（如 user:add）</td>
</tr>
<tr>
<td>name</td>
<td>varchar(50)</td>
<td>N</td>
<td>N</td>
<td>权限名称</td>
</tr>
<tr>
<td>resource_type</td>
<td>varchar(20)</td>
<td>N</td>
<td>N</td>
<td>资源类型（menu/button/api）</td>
</tr>
<tr>
<td>url</td>
<td>varchar(255)</td>
<td>N</td>
<td>Y</td>
<td>接口 URL</td>
</tr>
<tr>
<td>method</td>
<td>varchar(10)</td>
<td>N</td>
<td>Y</td>
<td>HTTP 方法（GET/POST 等）</td>
</tr>
<tr>
<td>parent_id</td>
<td>bigint</td>
<td>N</td>
<td>Y</td>
<td>父权限 ID（树形结构）</td>
</tr>
<tr>
<td>order_num</td>
<td>int</td>
<td>N</td>
<td>Y</td>
<td>排序权重</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>创建时间</td>
</tr>
</tbody></table>
<p>表 5-4 用户角色关联表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>user_id</td>
<td>bigint</td>
<td>Y（联合主键）</td>
<td>N</td>
<td>用户 ID</td>
</tr>
<tr>
<td>role_id</td>
<td>bigint</td>
<td>Y（联合主键）</td>
<td>N</td>
<td>角色 ID</td>
</tr>
</tbody></table>
<p>表 5-5 角色权限关联表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>role_id</td>
<td>bigint</td>
<td>Y（联合主键）</td>
<td>N</td>
<td>角色 ID</td>
</tr>
<tr>
<td>permission_id</td>
<td>bigint</td>
<td>Y（联合主键）</td>
<td>N</td>
<td>权限 ID</td>
</tr>
</tbody></table>
<p>表 5-6 登录日志表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>日志 ID</td>
</tr>
<tr>
<td>user_id</td>
<td>bigint</td>
<td>N</td>
<td>Y</td>
<td>用户 ID</td>
</tr>
<tr>
<td>username</td>
<td>varchar(64)</td>
<td>N</td>
<td>Y</td>
<td>用户名（冗余）</td>
</tr>
<tr>
<td>ip</td>
<td>varchar(50)</td>
<td>N</td>
<td>Y</td>
<td>登录 IP</td>
</tr>
<tr>
<td>location</td>
<td>varchar(100)</td>
<td>N</td>
<td>Y</td>
<td>IP 解析的地理位置</td>
</tr>
<tr>
<td>device</td>
<td>varchar(200)</td>
<td>N</td>
<td>Y</td>
<td>设备信息</td>
</tr>
<tr>
<td>status</td>
<td>tinyint(1)</td>
<td>N</td>
<td>N</td>
<td>登录结果（0-失败，1-成功）</td>
</tr>
<tr>
<td>error_msg</td>
<td>varchar(200)</td>
<td>N</td>
<td>Y</td>
<td>失败原因</td>
</tr>
<tr>
<td>login_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>登录时间</td>
</tr>
</tbody></table>
<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">图5<span class="hljs-string">-2</span>所示的用户登录流程图完整呈现了系统实现用户身份认证的核心流程，该流程通过分层验证机制（账户状态检查→密码匹配验证→权限树加载）确保安全准入，最终生成携带用户身份信息的JWT令牌并完成审计日志记录，各环节严格对应图5<span class="hljs-string">-1</span>类图设计的实体关系与功能方法。<br></code></pre></td></tr></table></figure>

<p>用户登录流程图。</p>
<pre><code class=" mermaid">flowchart TD
    A([开始]) --&gt; B[用户输入用户名密码]
    B --&gt; C&#123;系统验证&#125;
    C --&gt;|用户不存在/禁用/锁定| D[返回错误信息]
    C --&gt;|用户正常| E[验证密码]
    E --&gt;|密码错误| F[记录失败日志]
    F --&gt; G&#123;失败次数&gt;=5?&#125;
    G --&gt;|是| H[锁定账户]
    G --&gt;|否| D
    E --&gt;|密码正确| I[加载权限生成JWT]
    I --&gt; J[记录成功日志]
    J --&gt; K[返回令牌信息]
    K --&gt; L([结束])
    D --&gt; L
    H --&gt; D
</code></pre>

<figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile">当用户在前端页面输入用户名和密码并点击登录按钮时，系统首先会通过用户输入的用户名在数据库中查询对应的<span class="hljs-keyword">User</span>对象，如果用户不存在或状态为禁用/锁定则立即返回登录失败信息并记录到LoginLog中；如果用户存在且状态正常，则调用<span class="hljs-keyword">User</span>的checkPassword方法验证输入的密码是否与数据库中存储的加密密码匹配，密码验证失败会更新用户失败次数并在达到阈值时锁定账户，同时记录失败日志；密码验证通过后，系统会根据<span class="hljs-keyword">User</span>关联的Roles和Permissions生成该用户的完整权限集合，创建一个包含用户基本信息和权限的JWT令牌返回给前端，同时记录一条成功的LoginLog日志包含用户IP、设备和时间等信息，最后更新用户的最后登录时间。在整个流程中，任何异常情况都会触发相应的错误处理机制，确保系统安全性和数据一致性。这个流程涵盖了用户认证、权限处理、安全控制和日志记录等关键环节，为后续绘制详细的登录时序图提供了完整的逻辑基础。顺序图如图 <span class="hljs-number">5</span>-<span class="hljs-number">3</span>。<br></code></pre></td></tr></table></figure>

<p>绘制用户登录时序图。</p>
<pre><code class=" mermaid">%% 用户登录时序图
sequenceDiagram
    actor 用户 as 用户
    participant 前端 as 前端页面
    participant LoginController as LoginController
    participant AuthService as AuthService
    participant UserRepository as UserRepository
    participant User as User
    participant LoginLogService as LoginLogService
    participant JwtTokenUtil as JwtTokenUtil
    participant RolePermissionMapper as RolePermissionMapper

    用户 -&gt;&gt; 前端: 输入用户名/密码，点击登录
    前端 -&gt;&gt; LoginController: POST /api/login &#123;username, password&#125;
    LoginController -&gt;&gt; AuthService: authenticate(username, password)

    %% 用户验证阶段
    alt 用户不存在/禁用/锁定
        AuthService -&gt;&gt; UserRepository: findByUsername(username)
        UserRepository --&gt;&gt; AuthService: null 或 User(status=0/2)
        AuthService --&gt;&gt; LoginController: 抛出UserNotFoundException/AccountLockedException
        LoginController --&gt;&gt; 前端: 返回4xx错误及原因
        前端 --&gt;&gt; 用户: 显示错误提示
    else 用户正常
        AuthService -&gt;&gt; UserRepository: findByUsername(username)
        UserRepository --&gt;&gt; AuthService: User对象
        AuthService -&gt;&gt; User: checkPassword(inputPassword)

        %% 密码验证分支
        alt 密码错误
            User --&gt;&gt; AuthService: false
            AuthService -&gt;&gt; UserRepository: incrementFailedAttempts(userId)
            AuthService -&gt;&gt; LoginLogService: logFailure(userId, ip, &quot;密码错误&quot;)
            AuthService --&gt;&gt; LoginController: 抛出BadCredentialsException
            LoginController --&gt;&gt; 前端: 返回401错误
            前端 --&gt;&gt; 用户: 显示密码错误
        else 密码正确
            User --&gt;&gt; AuthService: true
            AuthService -&gt;&gt; RolePermissionMapper: loadPermissions(userId)
            RolePermissionMapper --&gt;&gt; AuthService: List&lt;Permission&gt;
            AuthService -&gt;&gt; JwtTokenUtil: generateToken(userDetails)
            JwtTokenUtil --&gt;&gt; AuthService: JWT令牌
            AuthService -&gt;&gt; LoginLogService: logSuccess(userId, ip, device)
            AuthService -&gt;&gt; UserRepository: updateLastLogin(userId, time)
            AuthService --&gt;&gt; LoginController: LoginResponse(JWT, userInfo)
            LoginController --&gt;&gt; 前端: 返回200及JWT
            前端 -&gt;&gt; 前端: localStorage.setItem(&quot;token&quot;, JWT)
            前端 --&gt;&gt; 用户: 跳转到首页
        end
    end
</code></pre>

<h3 id="选购下单实现"><a href="#选购下单实现" class="headerlink" title="选购下单实现"></a>选购下单实现</h3><blockquote>
<p>2025 年 4 月 11 日</p>
</blockquote>
<figure class="highlight excel"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs excel">商品选购下单模块包含商品展示、购物车管理、订单生成和支付处理，涉及到的类有商品类（<span class="hljs-built_in">Product</span>）、品牌类（Brand）、商品分类分类（Category）、订单类（Order）和订单详情类（OrderItem）。商品类中除了基本属性如name、<span class="hljs-built_in">price</span>和stock外，还包含reduceStock方法用于原子性扣减库存，isAvailable方法综合校验商品状态与库存。品牌类通过isActive方法验证品牌可用性，其logo和brandStory字段支撑前端品牌页展示。分类类借助getChildCategories方法构建多级分类树，productCount字段实现分类商品统计。订单类通过calculateFinalPrice方法计算实付金额（含促销、运费等），cancelOrder方法处理订单状态逆向流转并触发库存释放。这些类通过强关联协同工作，商品类关联唯一品牌类形成商品-品牌归属关系，关联唯一分类类建立商品-分类层级体系，订单类通过组合模式管理订单明细项（OrderItem），在明细中冗余存储商品快照信息（如brandName、categoryName），确保历史订单数据不受商品信息变更影响，共同完成从商品浏览到支付结算的完整电商交易闭环。类详细设计如下。<br></code></pre></td></tr></table></figure>

<p>选购下单类关系图。</p>
<pre><code class=" mermaid">classDiagram
    %% 1. 类定义（属性与数据库表字段严格对应）
    class Brand &#123;
        +id: Long
        +name: String
        +firstLetter: String
        +productCount: Integer
        +logo: String
        +brandStory: String
        +isActive() Boolean
    &#125;

    class Product &#123;
        +id: Long
        +name: String
        +description: String
        +price: BigDecimal
        +promotionPrice: BigDecimal
        +stock: Integer
        +lowStock: Integer
        +publishStatus: Integer
        +brandId: Long
        +productCategoryId: Long
        +reduceStock() Boolean
        +calculatePromotionPrice() BigDecimal
    &#125;

    class Category &#123;
        +id: Long
        +name: String
        +level: Integer
        +parentId: Long
        +productCount: Integer
        +productUnit: String
        +getChildCategories() List~Category~
    &#125;

    class Order &#123;
        +id: Long
        +totalAmount: BigDecimal
        +payAmount: BigDecimal
        +status: Integer
        +payType: Integer
        +deliverySn: String
        +calculateFinalPrice() BigDecimal
        +cancelOrder() Boolean
    &#125;

     class OrderItem &#123;
        +productName: String
        +brandName: String
        +categoryName
    &#125;

    %% 2. 关系定义（箭头类型与表外键匹配）
    Product &quot;1&quot; --&gt; &quot;1&quot; Brand : &quot;brand_id&quot;
    Product &quot;1&quot; --&gt; &quot;1&quot; Category : &quot;product_category_id&quot;
    Order &quot;1&quot; *-- &quot;n&quot; OrderItem : &quot;id&quot;
    Product ..&gt; OrderItem : &quot;快照关联&quot;
</code></pre>

<figure class="highlight elm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs elm">商品选购下单模块的数据库设计包含品牌管理、商品信息、分类体系、订单交易、购物车和评价系统，涉及的核心表包括品牌表（pms_brand）、商品信息表（pms_product）、商品分类表（pms_category）、订单表（oms_order）、购物车表（oms_cart）和商品评价表（pms_review）。品牌表通过id和name字段维护品牌基础信息，商品信息表以brand_id和product_category_id关联品牌与分类，并包含publish_status和promotion_<span class="hljs-keyword">type</span>字段管理上下架及促销状态。订单表通过member_id关联用户，status字段标记订单生命周期（0-待付款到5-无效订单），购物车表冗余存储product_brand和product_category_id确保数据一致性，商品评价表通过star和pics字段实现多维度的评价展示。所有表均包含create_time、update_time和is_delete字段实现软删除与审计追踪，构成完整的电商交易数据体系。数据库表结构如下：<br></code></pre></td></tr></table></figure>

<p>选购下单数据库表。</p>
<p>表 5-7 品牌表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>F</td>
<td>id</td>
</tr>
<tr>
<td>name</td>
<td>varchar(64)</td>
<td>F</td>
<td>F</td>
<td>品牌名称</td>
</tr>
<tr>
<td>first_letter</td>
<td>varchar(8)</td>
<td>F</td>
<td>F</td>
<td>首字母</td>
</tr>
<tr>
<td>product_count</td>
<td>int</td>
<td>F</td>
<td>F</td>
<td>产品数量</td>
</tr>
<tr>
<td>logo</td>
<td>varchar(255)</td>
<td>F</td>
<td>F</td>
<td>品牌 logo</td>
</tr>
<tr>
<td>brand_story</td>
<td>text</td>
<td>F</td>
<td>F</td>
<td>品牌故事</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>F</td>
<td>F</td>
<td>创建时间</td>
</tr>
<tr>
<td>update_time</td>
<td>datetime</td>
<td>F</td>
<td>F</td>
<td>更新时间</td>
</tr>
<tr>
<td>is_delete</td>
<td>int(1)</td>
<td>F</td>
<td>F</td>
<td>是否删除（0-&gt;已删除；1-&gt;未删除）</td>
</tr>
</tbody></table>
<p>表 5-8 商品信息表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>id</td>
</tr>
<tr>
<td>description</td>
<td>text</td>
<td>N</td>
<td>N</td>
<td>商品描述</td>
</tr>
<tr>
<td>brand_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>所属品牌</td>
</tr>
<tr>
<td>product_category_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>所属分类</td>
</tr>
<tr>
<td>product_attribute_category_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>所属属性分类</td>
</tr>
<tr>
<td>name</td>
<td>varchar(200)</td>
<td>N</td>
<td>N</td>
<td>商品名称</td>
</tr>
<tr>
<td>pic</td>
<td>varchar(255)</td>
<td>N</td>
<td>N</td>
<td>商品样图</td>
</tr>
<tr>
<td>publish_status</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>上架状态(0-&gt;下架；1-&gt;上架)</td>
</tr>
<tr>
<td>sale</td>
<td>int</td>
<td>N</td>
<td>N</td>
<td>销量</td>
</tr>
<tr>
<td>price</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>销售价格</td>
</tr>
<tr>
<td>promotion_price</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>促销价格</td>
</tr>
<tr>
<td>promotion_type</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>促销类型(0-&gt;使用原价;1-&gt;使用满减价格；2-&gt;使用促销价；4-&gt;限时购)</td>
</tr>
<tr>
<td>stock</td>
<td>int</td>
<td>N</td>
<td>N</td>
<td>库存</td>
</tr>
<tr>
<td>low_stock</td>
<td>int</td>
<td>N</td>
<td>N</td>
<td>库存预警值</td>
</tr>
<tr>
<td>weight</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>商品重量(默认为克)</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>创建时间</td>
</tr>
<tr>
<td>update_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>更新时间</td>
</tr>
<tr>
<td>is_delete</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>是否删除（0-&gt;已删除；1-&gt;未删除）</td>
</tr>
</tbody></table>
<p>表 5-9 商品分类表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>id</td>
</tr>
<tr>
<td>name</td>
<td>varchar(64)</td>
<td>N</td>
<td>N</td>
<td>分类名称</td>
</tr>
<tr>
<td>description</td>
<td>text</td>
<td>N</td>
<td>N</td>
<td>描述</td>
</tr>
<tr>
<td>parent_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>上级分类级别(0 表示一级分类)</td>
</tr>
<tr>
<td>level</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>所属分类级别(0-&gt;1 级；1-&gt;2 级)</td>
</tr>
<tr>
<td>product_count</td>
<td>int</td>
<td>N</td>
<td>N</td>
<td>商品数量</td>
</tr>
<tr>
<td>product_unit</td>
<td>varchar(64)</td>
<td>N</td>
<td>N</td>
<td>商品数量单位</td>
</tr>
<tr>
<td>icon</td>
<td>varchar(255)</td>
<td>N</td>
<td>N</td>
<td>图标</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>创建时间</td>
</tr>
<tr>
<td>update_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>更新时间</td>
</tr>
<tr>
<td>is_delete</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>是否删除（0-&gt;已删除；1-&gt;未删除）</td>
</tr>
</tbody></table>
<p>表 5-10 订单表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>id</td>
</tr>
<tr>
<td>member_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>下单用户</td>
</tr>
<tr>
<td>payment_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>支付时间</td>
</tr>
<tr>
<td>pay_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>实支金额</td>
</tr>
<tr>
<td>freight_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>运费金额</td>
</tr>
<tr>
<td>total_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>订单总金额</td>
</tr>
<tr>
<td>promotion_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>促销优化金额（促销价、满减）</td>
</tr>
<tr>
<td>coupon_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>优惠券抵扣金额</td>
</tr>
<tr>
<td>pay_type</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>支付方式(0-&gt;未支付；1-&gt;支付宝；2-&gt;微信)</td>
</tr>
<tr>
<td>status</td>
<td>Int(1)</td>
<td>N</td>
<td>N</td>
<td>订单状态(0-&gt;待付款；1-&gt;待发货；2-&gt;已发货；3-&gt;已完成；4-&gt;已关闭；5-&gt;无效订单)</td>
</tr>
<tr>
<td>receiver_name</td>
<td>varchar(100)</td>
<td>N</td>
<td>N</td>
<td>收货人姓名</td>
</tr>
<tr>
<td>receiver_phone</td>
<td>varchar(32)</td>
<td>N</td>
<td>N</td>
<td>收货人电话</td>
</tr>
<tr>
<td>note</td>
<td>varchar(500)</td>
<td>N</td>
<td>N</td>
<td>订单备注</td>
</tr>
<tr>
<td>delivery_company</td>
<td>varchar(64)</td>
<td>N</td>
<td>N</td>
<td>物流公司(配送方式)</td>
</tr>
<tr>
<td>delivery_sn</td>
<td>varchar(64)</td>
<td>N</td>
<td>N</td>
<td>物流单号</td>
</tr>
<tr>
<td>receiver_detail_address</td>
<td>varchar(200)</td>
<td>N</td>
<td>N</td>
<td>收货详细地址</td>
</tr>
<tr>
<td>confirm_status</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>确认收货状态(0-&gt;未确认；1-&gt;已确认)</td>
</tr>
<tr>
<td>delivery_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>发货时间</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>创建时间</td>
</tr>
<tr>
<td>update_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>更新时间</td>
</tr>
<tr>
<td>is_delete</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>是否删除（0-&gt;已删除；1-&gt;未删除）</td>
</tr>
</tbody></table>
<p>表 5-11 购物车表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>id</td>
</tr>
<tr>
<td>product_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>购买商品</td>
</tr>
<tr>
<td>member_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>购买用户</td>
</tr>
<tr>
<td>quantity</td>
<td>int</td>
<td>N</td>
<td>N</td>
<td>购买数量</td>
</tr>
<tr>
<td>price</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>需付金额</td>
</tr>
<tr>
<td>price_reduce</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>实付金额</td>
</tr>
<tr>
<td>product_pic</td>
<td>varchar(1000)</td>
<td>N</td>
<td>N</td>
<td>商品主图</td>
</tr>
<tr>
<td>product_category_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>所属分类</td>
</tr>
<tr>
<td>product_brand</td>
<td>varchar(200)</td>
<td>N</td>
<td>N</td>
<td>所属品牌</td>
</tr>
<tr>
<td>product_attr_id</td>
<td>varchar(500)</td>
<td>N</td>
<td>N</td>
<td>所属商品属性</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>创建时间</td>
</tr>
<tr>
<td>update_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>更新时间</td>
</tr>
<tr>
<td>is_delete</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>是否删除（0-&gt;已删除；1-&gt;未删除）</td>
</tr>
</tbody></table>
<p>表 5-12 商品评价表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>id</td>
</tr>
<tr>
<td>product_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>所属商品</td>
</tr>
<tr>
<td>member_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>所属用户</td>
</tr>
<tr>
<td>content</td>
<td>text</td>
<td>N</td>
<td>N</td>
<td>评价内容</td>
</tr>
<tr>
<td>star</td>
<td>int(3)</td>
<td>N</td>
<td>N</td>
<td>评价星数(0-5)</td>
</tr>
<tr>
<td>pics</td>
<td>varchar(1000)</td>
<td>N</td>
<td>N</td>
<td>上传图片地址(以逗号隔开)</td>
</tr>
<tr>
<td>collect_counnt</td>
<td>int</td>
<td>N</td>
<td>N</td>
<td>点赞数量</td>
</tr>
<tr>
<td>read_count</td>
<td>int</td>
<td>N</td>
<td>N</td>
<td>阅读数量</td>
</tr>
<tr>
<td>replay_count</td>
<td>int</td>
<td>N</td>
<td>N</td>
<td>回复数量</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>创建时间</td>
</tr>
<tr>
<td>update_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>更新时间</td>
</tr>
<tr>
<td>is_delete</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>是否删除（0-&gt;已删除；1-&gt;未删除）</td>
</tr>
</tbody></table>
<figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs reasonml">当用户在前端页面选择商品并触发addToCart操作时，系统首先通过<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">ProductService</span>.</span></span>checkStock方法校验商品库存状态，若库存不足或商品已下架则立即返回STOCK_LIMIT错误码；若库存充足则调用<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">CartService</span>.</span></span>addItem将商品数据写入购物车表，并返回实时计算的购物车总价。用户点击结算按钮时，前端调用<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">OrderService</span>.</span></span>createDraftOrder生成预订单，该方法内部通过<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">PromotionService</span>.</span></span>calculateDiscount计算满减、折扣等优惠规则，并执行<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">InventoryService</span>.</span></span>lockStock预占库存，最终返回包含订单号、实付金额的预订单数据。用户确认支付后，系统通过<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">PaymentService</span>.</span></span>process对接第三方支付渠道，支付成功时调用<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">OrderService</span>.</span></span>confirmPayment更新订单状态为<span class="hljs-string">&quot;待发货&quot;</span>，同步触发<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">InventoryService</span>.</span></span>confirmStockDeduction确认库存扣减和<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">CartService</span>.</span></span>clear清空购物车；若支付失败或超时，则通过<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">OrderService</span>.</span></span>cancelOrder回滚订单状态，并执行<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">InventoryService</span>.</span></span>releaseStock释放预占库存。整个流程通过<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Order</span>.</span></span>status状态机（<span class="hljs-number">0</span>-待付款→<span class="hljs-number">1</span>-待发货→<span class="hljs-number">3</span>-已完成）驱动业务流转，任何环节的异常都会通过标准化错误码（如PAY_TIMEOUT、STOCK_CONFLICT）中断流程并恢复数据一致性，确保在高并发场景下仍能维持库存准确性和订单最终状态的可追溯性。该流程完整覆盖了电商交易核心链路，为图<span class="hljs-number">5</span>-<span class="hljs-number">3</span>所示的时序图提供了精确的方法级交互基础。<br></code></pre></td></tr></table></figure>

<p>选购下单时序图。</p>
<pre><code class=" mermaid">sequenceDiagram
    actor 用户 as 用户
    participant 前端 as 前端
    participant ProductService as 商品服务
    participant CartService as 购物车服务
    participant OrderService as 订单服务
    participant PromotionService as 促销服务
    participant PaymentService as 支付服务
    participant InventoryService as 库存服务

    用户 -&gt;&gt; 前端: 添加商品到购物车
    前端 -&gt;&gt; ProductService: checkStock(productId, quantity)
    alt 库存充足
        ProductService --&gt; 前端: &#123;stock: 10, price: 99&#125;
        前端 -&gt;&gt; CartService: addItem(userId, productData)
        CartService --&gt; 前端: 更新后的购物车数据
    else 库存不足
        ProductService --&gt; 前端: &#123;errorCode: &quot;STOCK_LIMIT&quot;&#125;
    end

    用户 -&gt;&gt; 前端: 点击结算
    前端 -&gt;&gt; OrderService: createDraftOrder(cartItems)
    OrderService -&gt;&gt; PromotionService: calculateDiscount(cartItems)
    PromotionService --&gt; OrderService: &#123;discount: 20&#125;
    OrderService -&gt;&gt; InventoryService: lockStock(productId, quantity)
    OrderService --&gt; 前端: &#123;orderNo: &quot;NO123&quot;, amount: 79&#125;

    用户 -&gt;&gt; 前端: 确认支付
    前端 -&gt;&gt; PaymentService: process(orderNo, amount)
    alt 支付成功
        PaymentService -&gt;&gt; OrderService: confirmPayment(orderNo)
        OrderService -&gt;&gt; InventoryService: confirmStockDeduction(orderNo)
        OrderService -&gt;&gt; CartService: clear(userId)
        PaymentService --&gt; 前端: &#123;status: &quot;SUCCESS&quot;&#125;
    else 支付失败
        PaymentService --&gt; 前端: &#123;errorCode: &quot;PAY_FAILED&quot;&#125;
        OrderService -&gt;&gt; InventoryService: releaseStock(orderNo)
    end
</code></pre>

<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">当用户选择商品时，系统首先检查库存状态，库存充足则加入购物车，不足则提示；用户结算后生成待支付订单，支付成功则扣减库存并标记订单完成，支付失败或超时则释放预占库存并取消订单，最终形成从选购到订单终态的核心闭环流程。<br></code></pre></td></tr></table></figure>

<p>选购下单程序流程图。</p>
<pre><code class=" mermaid">flowchart TD
    A(开始) --&gt; B[选择商品]
    B --&gt; C&#123;库存检查&#125;
    C --&gt;|有货| D[加入购物车]
    C --&gt;|无货| E[提示库存不足]
    D --&gt; F[结算生成订单]
    F --&gt; G[支付处理]
    G --&gt;|成功| H[扣减库存]
    H --&gt; I[订单完成]
    G --&gt;|失败| J[释放库存]
    J --&gt; K[订单取消]
    I &amp; K --&gt; L(结束)
</code></pre>

<h3 id="订单管理实现"><a href="#订单管理实现" class="headerlink" title="订单管理实现"></a>订单管理实现</h3><blockquote>
<p>2025 年 4 月 11 日</p>
</blockquote>
<figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs scss">订单管理模块围绕订单主类（<span class="hljs-attribute">Order</span>）展开，关联订单明细类（OrderItem）、物流信息类（OrderDelivery）和操作日志类（OrderLog）。订单主类通过status字段驱动状态流转（<span class="hljs-number">0</span>待付款→<span class="hljs-number">1</span>待发货→<span class="hljs-number">3</span>已完成），其<span class="hljs-built_in">cancel</span>()方法处理取消逻辑并触发库存释放，<span class="hljs-built_in">confirmReceive</span>()方法完成收货确认。订单明细类通过productName和price等快照字段保留交易时商品状态，物流信息类依赖<span class="hljs-built_in">track</span>()方法实时查询物流轨迹，操作日志类记录所有关键操作（如取消、发货）。订单主类以组合关系管理明细（<span class="hljs-number">1</span>对多），以聚合关系关联物流信息（<span class="hljs-number">1</span>对<span class="hljs-number">1</span>），并通过日志形成完整审计链条，构成从创建到完结的闭环管理体系。<br></code></pre></td></tr></table></figure>

<p>订单实现类关系图。</p>
<pre><code class=" mermaid">classDiagram
    %% 订单主类（聚合根）
    class Order &#123;
        -id: Long
        -orderSn: String
        -userId: Long
        -totalAmount: BigDecimal
        -payAmount: BigDecimal
        -status: Integer
        -paymentTime: DateTime
        -deliverySn: String

        +cancel(): void
        +confirmReceive(): void
        +generateSn(): String
    &#125;

    %% 订单明细类（实体）
    class OrderItem &#123;
        -id: Long
        -orderId: Long
        -productId: Long
        -productName: String
        -price: BigDecimal
        -quantity: Integer

        +calcSubtotal(): BigDecimal
    &#125;

    %% 物流信息类（值对象）
    class OrderDelivery &#123;
        -id: Long
        -orderId: Long
        -deliveryCompany: String
        -deliverySn: String
        -receiverAddress: String

        +track(): String
    &#125;

    %% 操作日志类（实体）
    class OrderLog &#123;
        -id: Long
        -orderId: Long
        -action: String
        -operator: String

        +logAction(): void
    &#125;

    %% 关系定义
    Order &quot;1&quot; *-- &quot;n&quot; OrderItem : 包含 &gt;
    Order &quot;1&quot; o-- &quot;1&quot; OrderDelivery : 使用 &gt;
    Order &quot;1&quot; *-- &quot;n&quot; OrderLog : 记录 &gt;
</code></pre>

<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">订单管理模块的数据库设计围绕订单表（order）展开，通过订单明细表（order_item）记录商品快照信息，物流信息表（order_delivery）跟踪配送状态，操作日志表（order_log）审计关键操作。订单表以status字段（<span class="hljs-number">0</span>待付款<span class="hljs-regexp">/1待发货/</span><span class="hljs-number">2</span>已发货<span class="hljs-regexp">/3已完成）驱动核心流程，通过order_sn保证业务唯一性，并关联user_id标记用户归属；订单明细表通过order_id外联主订单，保留product_name和快照数据确保历史订单不受商品变更影响；物流信息表记录delivery_company和delivery_sn实现物流追踪；操作日志表通过action字段（如&quot;支付&quot;/</span><span class="hljs-string">&quot;取消&quot;</span>）和operator记录操作轨迹。所有表均包含create_time实现时间维度追溯，退货申请表（order_return）作为扩展支持售后流程，形成从订单创建、状态变更到最终完结的完整数据闭环。<br></code></pre></td></tr></table></figure>

<p>订单管理数据库表。</p>
<p>表 5-12 订单表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>id</td>
</tr>
<tr>
<td>member_id</td>
<td>bigint</td>
<td>N</td>
<td>N</td>
<td>下单用户</td>
</tr>
<tr>
<td>payment_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>支付时间</td>
</tr>
<tr>
<td>pay_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>实支金额</td>
</tr>
<tr>
<td>freight_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>运费金额</td>
</tr>
<tr>
<td>total_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>订单总金额</td>
</tr>
<tr>
<td>promotion_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>促销优化金额（促销价、满减）</td>
</tr>
<tr>
<td>coupon_amount</td>
<td>decimal(10, 2)</td>
<td>N</td>
<td>N</td>
<td>优惠券抵扣金额</td>
</tr>
<tr>
<td>pay_type</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>支付方式(0-&gt;未支付；1-&gt;支付宝；2-&gt;微信)</td>
</tr>
<tr>
<td>status</td>
<td>Int(1)</td>
<td>N</td>
<td>N</td>
<td>订单状态(0-&gt;待付款；1-&gt;待发货；2-&gt;已发货；3-&gt;已完成；4-&gt;已关闭；5-&gt;无效订单)</td>
</tr>
<tr>
<td>receiver_name</td>
<td>varchar(100)</td>
<td>N</td>
<td>N</td>
<td>收货人姓名</td>
</tr>
<tr>
<td>receiver_phone</td>
<td>varchar(32)</td>
<td>N</td>
<td>N</td>
<td>收货人电话</td>
</tr>
<tr>
<td>note</td>
<td>varchar(500)</td>
<td>N</td>
<td>N</td>
<td>订单备注</td>
</tr>
<tr>
<td>delivery_company</td>
<td>varchar(64)</td>
<td>N</td>
<td>N</td>
<td>物流公司(配送方式)</td>
</tr>
<tr>
<td>delivery_sn</td>
<td>varchar(64)</td>
<td>N</td>
<td>N</td>
<td>物流单号</td>
</tr>
<tr>
<td>receiver_detail_address</td>
<td>varchar(200)</td>
<td>N</td>
<td>N</td>
<td>收货详细地址</td>
</tr>
<tr>
<td>confirm_status</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>确认收货状态(0-&gt;未确认；1-&gt;已确认)</td>
</tr>
<tr>
<td>delivery_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>发货时间</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>创建时间</td>
</tr>
<tr>
<td>update_time</td>
<td>datetime</td>
<td>N</td>
<td>N</td>
<td>更新时间</td>
</tr>
<tr>
<td>is_delete</td>
<td>int(1)</td>
<td>N</td>
<td>N</td>
<td>是否删除（0-&gt;已删除；1-&gt;未删除）</td>
</tr>
</tbody></table>
<p>表 5-13 订单明细表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>明细 ID</td>
</tr>
<tr>
<td>order_id</td>
<td>bigint</td>
<td></td>
<td>N</td>
<td>关联订单 ID</td>
</tr>
<tr>
<td>product_id</td>
<td>bigint</td>
<td></td>
<td>Y</td>
<td>商品 ID（允许商品删除后为空）</td>
</tr>
<tr>
<td>product_name</td>
<td>varchar(200)</td>
<td></td>
<td>N</td>
<td>商品名称快照</td>
</tr>
<tr>
<td>price</td>
<td>decimal(10,2)</td>
<td></td>
<td>N</td>
<td>成交单价快照</td>
</tr>
<tr>
<td>quantity</td>
<td>int</td>
<td></td>
<td>N</td>
<td>购买数量</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td></td>
<td>N</td>
<td>创建时间</td>
</tr>
</tbody></table>
<p>表 5-14 订单操作日志表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>物流记录 ID</td>
</tr>
<tr>
<td>order_id</td>
<td>bigint</td>
<td></td>
<td>N</td>
<td>关联订单 ID</td>
</tr>
<tr>
<td>delivery_company</td>
<td>varchar(32)</td>
<td></td>
<td>N</td>
<td>物流公司（如顺丰、中通）</td>
</tr>
<tr>
<td>delivery_sn</td>
<td>varchar(64)</td>
<td></td>
<td>N</td>
<td>物流单号</td>
</tr>
<tr>
<td>receiver_address</td>
<td>varchar(200)</td>
<td></td>
<td>N</td>
<td>完整收货地址</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td></td>
<td>N</td>
<td>创建时间</td>
</tr>
</tbody></table>
<p>表 5-15 物流信息表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>物流记录 ID</td>
</tr>
<tr>
<td>order_id</td>
<td>bigint</td>
<td></td>
<td>N</td>
<td>关联订单 ID</td>
</tr>
<tr>
<td>delivery_company</td>
<td>varchar(32)</td>
<td></td>
<td>N</td>
<td>物流公司（如顺丰、中通）</td>
</tr>
<tr>
<td>delivery_sn</td>
<td>varchar(64)</td>
<td></td>
<td>N</td>
<td>物流单号</td>
</tr>
<tr>
<td>receiver_address</td>
<td>varchar(200)</td>
<td></td>
<td>N</td>
<td>完整收货地址</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td></td>
<td>N</td>
<td>创建时间</td>
</tr>
</tbody></table>
<p>表 5-16 退货申请表</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>数据类型</th>
<th>主键</th>
<th>是否为空</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>bigint</td>
<td>Y</td>
<td>N</td>
<td>退货 ID</td>
</tr>
<tr>
<td>order_id</td>
<td>bigint</td>
<td></td>
<td>N</td>
<td>关联订单 ID</td>
</tr>
<tr>
<td>product_id</td>
<td>bigint</td>
<td></td>
<td>N</td>
<td>退货商品 ID</td>
</tr>
<tr>
<td>reason</td>
<td>varchar(200)</td>
<td></td>
<td>N</td>
<td>退货原因</td>
</tr>
<tr>
<td>status</td>
<td>int</td>
<td></td>
<td>N</td>
<td>状态（0 待处理/1 通过/2 拒绝）</td>
</tr>
<tr>
<td>create_time</td>
<td>datetime</td>
<td></td>
<td>N</td>
<td>申请时间</td>
</tr>
</tbody></table>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">流程始于用户提交订单，系统首先检查库存，充足则生成预订单（状态<span class="hljs-number">0</span>），不足则直接终止；用户支付时分支判断：成功则扣减库存、生成物流单并更新状态为<span class="hljs-number">1</span>，失败则释放库存；发货后用户可查询物流轨迹，最终确认收货将状态置为<span class="hljs-number">3</span>。流程以订单状态（<span class="hljs-number">0</span><span class="hljs-regexp">/1/</span><span class="hljs-number">3</span>）为核心驱动，库存操作（预占<span class="hljs-regexp">/扣减/</span>释放）和物流生成作为关键子流程，异常路径（如支付超时）自动触发状态回滚，形成从创建到完成的线性闭环。<br></code></pre></td></tr></table></figure>

<p>订单管理程序流图。</p>
<pre><code class=" mermaid">flowchart TD
    A([开始]) --&gt; B&#123;用户操作&#125;
    B --&gt;|提交订单| C[库存预占]
    C --&gt; D&#123;库存充足?&#125;
    D --&gt;|是| E[生成预订单\n状态=0]
    D --&gt;|否| F[返回库存不足]
    E --&gt; G&#123;用户操作&#125;
    G --&gt;|确认支付| H[调用支付接口]
    H --&gt; I&#123;支付成功?&#125;
    I --&gt;|是| J[扣减库存]
    J --&gt; K[生成物流单]
    K --&gt; L[更新订单\n状态=1]
    I --&gt;|否| M[释放库存]
    M --&gt; N[保持状态=0]
    L --&gt; O&#123;用户操作&#125;
    O --&gt;|查询物流| P[获取物流轨迹]
    O --&gt;|确认收货| Q[更新订单\n状态=3]
    Q --&gt; R([结束])
    N --&gt; R
    F --&gt; R
</code></pre>

<figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs scss">当用户提交订单时，系统调用OrderService<span class="hljs-selector-class">.createOrder</span>()预占库存并生成待支付订单（状态<span class="hljs-number">0</span>）；用户支付成功后，PaymentService触发<span class="hljs-built_in">confirmPayment</span>()更新订单状态为<span class="hljs-number">1</span>（待发货），同步扣减库存并生成物流单；支付失败时通过<span class="hljs-built_in">cancelOrder</span>()释放库存。用户可通过DeliveryService<span class="hljs-selector-class">.track</span>()查询物流轨迹，确认收货后调用<span class="hljs-built_in">confirmReceive</span>()将状态更新为<span class="hljs-number">3</span>（已完成）。全流程通过OrderLog记录操作日志，任何异常（如库存不足、支付超时）均中断流程并恢复数据一致性，确保订单状态与库存、物流的严格同步。<br></code></pre></td></tr></table></figure>

<p>订单管理时序图。</p>
<pre><code class=" mermaid">sequenceDiagram
    actor 用户 as 用户
    participant 前端 as 前端
    participant OrderService as 订单服务
    participant PaymentService as 支付服务
    participant InventoryService as 库存服务
    participant DeliveryService as 物流服务

    用户 -&gt;&gt; 前端: 提交订单
    前端 -&gt;&gt; OrderService: createOrder(商品列表)
    OrderService -&gt;&gt; InventoryService: lockStock(商品ID,数量)
    InventoryService --&gt;&gt; OrderService: 锁定结果
    OrderService --&gt;&gt; 前端: 返回预订单(状态0)

    用户 -&gt;&gt; 前端: 确认支付
    前端 -&gt;&gt; PaymentService: processPayment(订单ID)
    alt 支付成功
        PaymentService -&gt;&gt; OrderService: confirmPayment(订单ID)
        OrderService -&gt;&gt; InventoryService: confirmDeduction(订单ID)
        OrderService -&gt;&gt; DeliveryService: prepareDelivery(订单ID)
        DeliveryService --&gt;&gt; OrderService: 物流单号
        OrderService --&gt;&gt; 前端: 支付成功(状态1)
    else 支付失败
        PaymentService -&gt;&gt; OrderService: cancelOrder(订单ID)
        OrderService -&gt;&gt; InventoryService: releaseStock(订单ID)
        OrderService --&gt;&gt; 前端: 支付失败(状态0)
    end

    用户 -&gt;&gt; 前端: 查询物流
    前端 -&gt;&gt; DeliveryService: track(物流单号)
    DeliveryService --&gt;&gt; 前端: 返回物流轨迹

    用户 -&gt;&gt; 前端: 确认收货
    前端 -&gt;&gt; OrderService: confirmReceive(订单ID)
    OrderService -&gt;&gt; OrderLog: 记录操作日志
    OrderService --&gt;&gt; 前端: 订单完成(状态3)
</code></pre>

<h2 id="需求分析"><a href="#需求分析" class="headerlink" title="需求分析"></a>需求分析</h2><blockquote>
<p>2025 年 4 月 12 日</p>
</blockquote>
<p>整体用例图。</p>
<pre><code class=" mermaid">%%&#123;init: &#123;&#x27;theme&#x27;: &#x27;base&#x27;, &#x27;themeVariables&#x27;: &#123; &#x27;primaryColor&#x27;: &#x27;#1a1a1a&#x27;, &#x27;actorBorder&#x27;: &#x27;#ffffff&#x27;&#125;&#125;&#125;%%
graph TD
    %% 参与者定义
    actor1((&quot;消费者&quot;))
    actor2((&quot;管理员&quot;))

    %% 前台系统用例
    A[浏览智能推荐商品]
    B[查看商品详情]
    C[购物车管理]
    D[下单支付]
    E[参与促销活动]
    F[管理个人空间]
    F1[查看订单]
    F2[管理收货地址]
    F3[管理收藏夹]

    %% 后台系统用例
    G[商品管理]
    G1[上架商品]
    G2[商品分类管理]
    H[订单管理]
    H1[物流跟踪]
    I[营销管理]
    I1[活动配置]
    J[用户管理]
    K[权限管理]
    K1[角色分配]

    %% 连接关系
    actor1 --&gt; A
    actor1 --&gt; B
    actor1 --&gt; C
    actor1 --&gt; D
    actor1 --&gt; E
    actor1 --&gt; F
    F --&gt; F1
    F --&gt; F2
    F --&gt; F3
    D -.-&gt;|&lt;&lt;include&gt;&gt;| H1
    E -.-&gt;|&lt;&lt;include&gt;&gt;| I1

    actor2 --&gt; G
    actor2 --&gt; H
    actor2 --&gt; I
    actor2 --&gt; J
    actor2 --&gt; K
    G --&gt; G1
    G --&gt; G2
    H --&gt; H1
    I --&gt; I1
    K --&gt; K1
</code></pre>

<p>选购下单用例图。</p>
<pre><code class=" mermaid">%%&#123;init: &#123;&#x27;theme&#x27;: &#x27;base&#x27;, &#x27;themeVariables&#x27;: &#123; &#x27;primaryColor&#x27;: &#x27;#1a1a1a&#x27;, &#x27;actorBorder&#x27;: &#x27;#ffffff&#x27;&#125;&#125;&#125;%%
graph TD
    %% 参与者定义（简笔画风格）
    actor_consumer((&quot;消费者&quot;))
    actor_admin((&quot;管理员&quot;))

    %% 前台功能（白色椭圆框）

    uc1[商品浏览]
    uc2[商品筛选]
    uc3[规格选择]
    uc4[订单确认]
    uc5[支付订单]

    %% 后台功能（白色椭圆框）
    uc6[商品管理]
    uc7[订单管理]
    uc8[库存管理]

    %% 前台流程连接
    actor_consumer --&gt; uc1
    uc1 --&gt;|&lt;&lt;include&gt;&gt;| uc2
    uc2 --&gt; uc3
    uc3 --&gt; uc4
    uc4 --&gt;|&lt;&lt;include&gt;&gt;| uc5
    uc5 -.-&gt;|触发| uc8

    %% 后台管理连接
    actor_admin --&gt; uc6
    actor_admin --&gt; uc7
    uc6 --&gt;|&lt;&lt;extend&gt;&gt;| uc8
    uc7 --&gt;|&lt;&lt;extend&gt;&gt;| uc4
</code></pre>

<pre><code class=" mermaid">graph LR
   商品管理 -- &quot;包含（必须调用）&quot; --&gt; 库存管理
</code></pre>

<p>订单管理用例图。</p>
<pre><code class=" mermaid">%%&#123;init: &#123;&#x27;theme&#x27;: &#x27;base&#x27;, &#x27;themeVariables&#x27;: &#123; &#x27;primaryColor&#x27;: &#x27;#1a1a1a&#x27;, &#x27;actorBorder&#x27;: &#x27;#ffffff&#x27;&#125;&#125;&#125;%%
graph TD
    %% 参与者定义
    actor_consumer((&quot;消费者&quot;))
    actor_admin((&quot;管理员&quot;))

    %% 核心状态节点（白色椭圆框）
    s1[待付款]
    s2[待发货]
    s3[已发货]
    s4[已完成]
    s5[已关闭]
    s6[退货处理]

    %% 功能操作节点
    o1[订单列表展示]
    o2[查看订单状态]
    o3[订单筛选]
    o4[删除订单]
    o5[退货申请处理]
    o6[退货原因设置]

    %% 状态流转（实线箭头）
    s1 --&gt;|支付成功| s2
    s1 --&gt;|超时未付| s5
    s2 --&gt;|商家发货| s3
    s3 --&gt;|签收| s4
    s3 --&gt;|发起退货| s6
    s6 --&gt;|处理完成| s5

    %% 功能连接（虚线箭头）
    actor_consumer -.-&gt; o1
    actor_consumer -.-&gt; o2
    actor_admin --&gt; o3
    actor_admin --&gt; o4
    actor_admin --&gt; o5
    actor_admin --&gt; o6
    o5 --&gt; s6

    %% 特殊关系标注
    o1 .-&gt;|&lt;&lt;include&gt;&gt;| o2
    o5 .-&gt;|&lt;&lt;extend&gt;&gt;| o6
</code></pre>

<p>系统类关系图。</p>
<pre><code class=" mermaid">%%&#123;init: &#123;&#x27;theme&#x27;: &#x27;base&#x27;, &#x27;themeVariables&#x27;: &#123; &#x27;primaryColor&#x27;: &#x27;#f8f9fa&#x27;, &#x27;classText&#x27;: &#x27;#333&#x27;&#125;&#125;&#125;%%
classDiagram
    %% 用户中心模块
    class User &#123;
    &#125;
    class Role &#123;
    &#125;
    class Permission &#123;
    &#125;
    class LoginLog &#123;
    &#125;

    User &quot;1&quot; *-- &quot;1..*&quot; Role : 聚合
    Role &quot;1&quot; *-- &quot;n&quot; Permission : 组合
    User &quot;1&quot; --&gt; &quot;n&quot; LoginLog : 关联

    %% 商品中心模块
    class Product &#123;
    &#125;
    class Brand &#123;
    &#125;
    class Category &#123;
    &#125;
    class ProductAttribute &#123;
    &#125;

    Product &quot;1&quot; *-- &quot;1&quot; Brand : 聚合
    Product &quot;1&quot; *-- &quot;1&quot; Category : 聚合
    Product &quot;1&quot; *-- &quot;n&quot; ProductAttribute : 组合

    %% 订单中心模块
    class Order &#123;
    &#125;
    class OrderItem &#123;
    &#125;
    class OrderDelivery &#123;
    &#125;
    class OrderLog &#123;
    &#125;
    class PaymentInfo &#123;
    &#125;

    Order &quot;1&quot; *-- &quot;n&quot; OrderItem : 组合
    Order &quot;1&quot; --&gt; &quot;1&quot; OrderDelivery : 关联
    Order &quot;1&quot; --&gt; &quot;n&quot; OrderLog : 关联
    Order &quot;1&quot; --&gt; &quot;1&quot; PaymentInfo : 组合

    %% 跨模块关系
    User &quot;1&quot; --&gt; &quot;n&quot; Order : 关联
    Product &quot;1&quot; --&gt; &quot;n&quot; OrderItem : 关联
    Category &quot;1&quot; --&gt; &quot;n&quot; Category : 自关联
    Brand ..&gt; OrderItem : 依赖

</code></pre>

<blockquote>
<p>2025 年 4 月 13 日</p>
</blockquote>
<p>类关系图，类设计。</p>
<pre><code class=" mermaid">%%&#123;init: &#123;&#x27;theme&#x27;: &#x27;base&#x27;, &#x27;themeVariables&#x27;: &#123; &#x27;primaryColor&#x27;: &#x27;#f8f9fa&#x27;, &#x27;classText&#x27;: &#x27;#333&#x27;&#125;&#125;&#125;%%
classDiagram
    %% 用户中心模块
    class User &#123;
        +用户ID
        +用户名
        +密码(加密)
        +手机号
        +注册时间
        +login()
        +logout()
        +getUserInfo()
    &#125;
    class Role &#123;
        +角色ID
        +角色名称
        +描述
        +assignPermission()
        +checkPermission()
    &#125;
    class Permission &#123;
        +权限ID
        +权限码
        +描述
        +verify()
    &#125;
    class LoginLog &#123;
        +日志ID
        +登录IP
        +登录时间
        +记录日志()
    &#125;

    User &quot;1&quot; *-- &quot;1..*&quot; Role : 聚合
    Role &quot;1&quot; *-- &quot;n&quot; Permission : 组合
    User &quot;1&quot; --&gt; &quot;n&quot; LoginLog : 关联

    %% 商品中心模块
    class Product &#123;
        +商品ID
        +商品名称
        +库存量
        +售价
        +上架状态
        +addToCart()
        +updateStock()
    &#125;
    class Brand &#123;
        +品牌ID
        +品牌名称
        +logo地址
        +getBrandInfo()
    &#125;
    class Category &#123;
        +分类ID
        +分类名称
        +父分类ID
        +getSubCategories()
    &#125;
    class ProductAttribute &#123;
        +属性ID
        +属性名
        +
        +bindToProduct()
    &#125;

    Product &quot;1&quot; *-- &quot;1&quot; Brand : 聚合
    Product &quot;1&quot; *-- &quot;1&quot; Category : 聚合
    Product &quot;1&quot; *-- &quot;n&quot; ProductAttribute : 组合

    %% 订单中心模块
    class Order &#123;
        +订单ID
        +订单状态
        +总金额
        +下单时间
        +calculateTotal()
        +changeStatus()
    &#125;
    class OrderItem &#123;
        +订单项ID
        +购买数量
        +成交价
        +calculateSubtotal()
    &#125;
    class OrderDelivery &#123;
        +物流单号
        +收货地址
        +发货时间
        +trackDelivery()
    &#125;
    class PaymentInfo &#123;
        +支付单号
        +支付方式
        +支付状态
        +processPayment()
    &#125;

    Order &quot;1&quot; *-- &quot;n&quot; OrderItem : 组合
    Order &quot;1&quot; --&gt; &quot;1&quot; OrderDelivery : 关联
    Order &quot;1&quot; --&gt; &quot;1&quot; PaymentInfo : 组合

    %% 跨模块关系
    User &quot;1&quot; --&gt; &quot;n&quot; Order : 关联
    Product &quot;1&quot; --&gt; &quot;n&quot; OrderItem : 关联
    Category &quot;1&quot; --&gt; &quot;n&quot; Category : 自关联
    Brand ..&gt; OrderItem : 依赖
</code></pre>

<h2 id="功能结构-1"><a href="#功能结构-1" class="headerlink" title="功能结构"></a>功能结构</h2><blockquote>
<p>2025 年 4 月 13 日</p>
</blockquote>
<pre><code class=" mermaid">graph TD
    A[汽配销售管理系统] --&gt; B[前台功能]
    A --&gt; C[后台功能]

    %% 前台功能模块
    B --&gt; B1[用户认证]
    B1 --&gt;|包含| B11(登录)
    B1 --&gt;|包含| B12(注册)

    B --&gt; B2[个人中心]
    B2 --&gt;|包含| B21(个人信息管理)
    B2 --&gt;|包含| B22(收货地址管理)

    B --&gt; B3[商品服务]
    B3 --&gt;|包含| B31(首页门户)
    B3 --&gt;|包含| B32(商品推荐)
    B3 --&gt;|包含| B33(商品搜索)
    B3 --&gt;|包含| B34(商品展示)

    B --&gt; B4[交易流程]
    B4 --&gt;|包含| B41(购物车)
    B4 --&gt;|包含| B42(订单流程)
    B4 --&gt;|包含| B43(支付管理)

    B --&gt; B5[辅助功能]
    B5 --&gt;|包含| B51(帮助中心)
    B5 --&gt;|包含| B52(客服服务)

    %% 后台功能模块
    C --&gt; C1[商品管理]
    C1 --&gt;|包含| C11(商品上架)
    C1 --&gt;|包含| C12(库存管理)
    C1 --&gt;|包含| C13(品牌/分类管理)

    C --&gt; C2[订单管理]
    C2 --&gt;|包含| C21(订单审核)
    C2 --&gt;|包含| C22(物流跟踪)
    C2 --&gt;|包含| C23(退换货处理)

    C --&gt; C3[营销管理]
    C3 --&gt;|包含| C31(促销活动)
    C3 --&gt;|包含| C32(优惠券管理)

    C --&gt; C4[用户管理]
    C4 --&gt;|包含| C41(用户权限)
    C4 --&gt;|包含| C42(角色管理)

    C --&gt; C5[系统管理]
    C5 --&gt;|包含| C51(内容管理)
    C5 --&gt;|包含| C52(财务管理)
    C5 --&gt;|包含| C53(数据统计)
</code></pre>

<h2 id="查重"><a href="#查重" class="headerlink" title="查重"></a>查重</h2><blockquote>
<p>2025 年 4 月 23 日</p>
</blockquote>
<p>不得不说这是个好消息。</p>
<p>今天早上，这项工作圆满结束了。</p>
<p><a target="_blank" rel="noopener" href="https://jj.zaojiangchong.com/">早降重论文降重系统官网<em>解决毕业论文重复率高</em>机器智能降重_论文润色修改 (zaojiangchong.com)</a></p>
<p>这个工具倒也挺好用。</p>
<p><img src="http://blog.memory-life.xyz/image-20250423204254467.png" alt="image-20250423204254467"></p>
<p><img src="http://blog.memory-life.xyz/image-20250423204328012.png" alt="image-20250423204328012"></p>
<p><img src="http://blog.memory-life.xyz/image-20250423204342674.png" alt="image-20250423204342674"></p>
<p>整整两周，总算结束了，开启下一个阶段。</p>
<blockquote>
<p>2025 年 4 月 21 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://vpcs.fanyu.com/paper/index">论文检测 (fanyu.com)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250421122822491.png" alt="image-20250421122822491"></p>
<p>维普查重真要命，查重率，AIGC，格式，艹。</p>
<p>AIGC 文段汇总。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">内容摘要：本文设计并实现了一个基于JavaWeb的汽配销售管理系统，旨在解决传统汽配销售模式效率低下、管理粗放的问题。系统采用SpringBoot框架开发，整合了MySQL数据库、MyBatis等技术，实现了前后端分离的模块化架构。系统角色包括管理员和消费者两类，实现了面向消费者的商品选购、订单支付功能和面向管理员的商品管理、订单处理、用户权限控制等后台管理功能；通过可行性分析验证了经济、操作及技术层面的可行性，基于角色用例分析设计了消费者和管理员两类用户的操作流程，并通过数据库逻辑设计构建了19张核心数据表，覆盖商品、订单、营销等业务场景。系统测试表明，该系统的实现能有效提升汽配销售企业的运营效率，优化客户体验，并为行业数字化转型提供参考。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs reasonml">在传统的汽配商品销售模式中免不了出现效率低下、管理粗放等问题，故本论文设计并实现了一个基于JavaWeb的汽配销售管理系统。该系统采用当今市面上Java主流开发框架实现，其中后台系统使用SpringBoot框架整合MyBatis、MySQL数据库等技术，而前台界面则使用<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Vue</span>.</span></span>js技术实现用户点击交互。普通消费者可以在前台前台商城中进行汽配商品检索及浏览、选购下单以及订单支付，后台管理员则主要负责商品管理、订单流程追踪以及用户权限控制等后台管理功能。在投入系统开发前，认真讨论并验证了该系统在经济、操作和技术层面的可信性，合理规划并整理出核心功能列表，并绘制与之对应的用例分析图。除此之外，结合前面列举的核心功能列表，使用MySQL数据库设计了总计<span class="hljs-number">19</span>张核心数据库表，覆盖了汽配销售的多个业务场景。在核心功能开发完毕后，在系统测试环节中设计了全面的测试用例，检验逐步完善该系统健壮性，提升用户体验。<br></code></pre></td></tr></table></figure>

<figure class="highlight vbnet"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs vbnet">Abstract This paper presents the design <span class="hljs-built_in">and</span> implementation <span class="hljs-keyword">of</span> a JavaWeb-based <span class="hljs-keyword">auto</span> parts sales management system <span class="hljs-keyword">to</span> address the inefficiencies <span class="hljs-built_in">and</span> poor management <span class="hljs-keyword">in</span> traditional sales models. Developed <span class="hljs-keyword">using</span> the SpringBoot framework, the system integrates technologies such <span class="hljs-keyword">as</span> MySQL <span class="hljs-built_in">and</span> MyBatis, adopting a modular architecture <span class="hljs-keyword">with</span> front-<span class="hljs-keyword">end</span> <span class="hljs-built_in">and</span> back-<span class="hljs-keyword">end</span> separation.The system features two user roles (administrator <span class="hljs-built_in">and</span> consumer), providing consumer-oriented functions <span class="hljs-built_in">like</span> product selection <span class="hljs-built_in">and</span> <span class="hljs-keyword">order</span> payment, <span class="hljs-keyword">as</span> well <span class="hljs-keyword">as</span> administrator-focused backend management including product management, <span class="hljs-keyword">order</span> processing, <span class="hljs-built_in">and</span> user permission control.Feasibility analysis confirms the system<span class="hljs-comment">&#x27;s viability in economic, operational, and technical aspects. Role-based use case analysis defines workflows for both consumers and administrators, while logical database design establishes 19 core tables covering business scenarios like products, orders, and marketing. System testing demonstrates that this solution effectively enhances operational efficiency for auto parts enterprises, optimizes customer experience, and serves as a reference for industry digital transformation.</span><br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pgsql"><span class="hljs-keyword">In</span> the traditional sales model <span class="hljs-keyword">of</span> auto parts commodities, problems such <span class="hljs-keyword">as</span> low efficiency <span class="hljs-keyword">and</span> rough management are inevitable. Therefore, this paper designs <span class="hljs-keyword">and</span> implements an auto parts sales management <span class="hljs-keyword">system</span> based <span class="hljs-keyword">on</span> JavaWeb. This <span class="hljs-keyword">system</span> <span class="hljs-keyword">is</span> implemented <span class="hljs-keyword">by</span> adopting the mainstream Java development framework currently available <span class="hljs-keyword">on</span> the market. Among them, the back-<span class="hljs-keyword">end</span> <span class="hljs-keyword">system</span> uses the SpringBoot framework <span class="hljs-keyword">to</span> integrate technologies such <span class="hljs-keyword">as</span> MyBatis <span class="hljs-keyword">and</span> MySQL databases, <span class="hljs-keyword">while</span> the front-<span class="hljs-keyword">end</span> interface uses Vue.js technology <span class="hljs-keyword">to</span> achieve <span class="hljs-keyword">user</span> click interaction. Ordinary consumers can <span class="hljs-keyword">search</span> <span class="hljs-keyword">and</span> browse auto parts products, <span class="hljs-keyword">select</span> <span class="hljs-keyword">and</span> place orders, <span class="hljs-keyword">and</span> make <span class="hljs-keyword">order</span> payments <span class="hljs-keyword">in</span> the front-<span class="hljs-keyword">end</span> mall. The back-<span class="hljs-keyword">end</span> administrators are mainly responsible <span class="hljs-keyword">for</span> back-<span class="hljs-keyword">end</span> management <span class="hljs-keyword">functions</span> such <span class="hljs-keyword">as</span> product management, <span class="hljs-keyword">order</span> process tracking, <span class="hljs-keyword">and</span> <span class="hljs-keyword">user</span> permission control. <span class="hljs-keyword">Before</span> devoting <span class="hljs-keyword">to</span> the <span class="hljs-keyword">system</span> development, the credibility <span class="hljs-keyword">of</span> the <span class="hljs-keyword">system</span> at the economic, operational <span class="hljs-keyword">and</span> technical levels was carefully discussed <span class="hljs-keyword">and</span> verified. The core <span class="hljs-keyword">function</span> list was reasonably planned <span class="hljs-keyword">and</span> sorted <span class="hljs-keyword">out</span>, <span class="hljs-keyword">and</span> the corresponding use <span class="hljs-keyword">case</span> analysis diagram was drawn. <span class="hljs-keyword">In</span> addition, combined <span class="hljs-keyword">with</span> the list <span class="hljs-keyword">of</span> core <span class="hljs-keyword">functions</span> listed earlier, a total <span class="hljs-keyword">of</span> <span class="hljs-number">19</span> core <span class="hljs-keyword">database</span> <span class="hljs-keyword">tables</span> were designed <span class="hljs-keyword">using</span> the MySQL <span class="hljs-keyword">database</span>, covering multiple business scenarios <span class="hljs-keyword">of</span> auto parts sales. <span class="hljs-keyword">After</span> the core <span class="hljs-keyword">functions</span> were developed, comprehensive test cases were designed <span class="hljs-keyword">in</span> the <span class="hljs-keyword">system</span> testing stage <span class="hljs-keyword">to</span> verify <span class="hljs-keyword">and</span> gradually improve the robustness <span class="hljs-keyword">of</span> the <span class="hljs-keyword">system</span> <span class="hljs-keyword">and</span> enhance the <span class="hljs-keyword">user</span> experience.<br></code></pre></td></tr></table></figure>

<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mipsasm">当今社会，汽配销售行业正面临着前所未有的挑战和机遇，信息技术日新月异，消费者需求日益多样化。传统的汽配销售管理模式已经难以满足现代市场的需求，企业急需一种高效智能的汽配销售管理系统来提升客户服务质量并增强市场竞争力。 通过设计和实现基于<span class="hljs-keyword">Java </span>Web的汽配销售管理系统，企业可以更加高效地管理销售流程、优化库存配置、提升客户服务质量。系统的实现将推动汽配销售行业向数字化、智能化方向发展，促进技术创新和业务模式创新，为企业带来新的增长点和竞争优势。 这种系统有助于汽配销售企业更好地了解市场需求，提高市场反应速度。研究和分析汽配销售管理系统具有重要的现实意义，有助于推动汽配销售行业的技术创新和管理创新，提高整个行业的竞争力，为消费者提供更加优质的购车体验。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">当今社会信息技术日新月异，消费者需求也日益多样化，传统的汽配销售行业正处于转型关键期。随着市场变化更加不可控，过去传统的的汽配销售管理方式显然已经落伍于新时代发展需求，当下的企业迫切需要更加智能的系统来提升服务水平和竞争力。基于Java主流技术栈设计和实现的汽配销售管理系统，恰恰能够迎合大众的汽配商品购买需求，其无论在提升用户体验或是企业管理方面，都具有显著的市场竞争力。在业务流程方面，此类系统在保持原有汽配销售理念不变的条件下，选择极大简化销售环节，通过智能管理方案提升服务效率。用户一旦选择使用此类汽配销售管理系统，就能享受到更便捷的选购流程、更精准的配件推荐以及更完善的售后服务。此外从企业的角度来看，合理使用更加完善的智能化服务，能够解决不同用户的个性化需求，在改善广大客户体验的同时，同样也有利于企业快速掌握市场新动向，为将来可能面临的销售策略调整做好充足准备。<br></code></pre></td></tr></table></figure>

<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mipsasm">从行业发展的角度来看，汽配销售管理系统的研究与优化是推动汽配销售行业数字化转型的关键一步。随着信息技术的飞速发展，传统汽配销售模式已经难以满足现代市场的需求和变化。通过研究和优化汽配销售管理系统，可以有效提高运营效率，降低成本。 其次，从客户体验的角度来看，汽配销售管理系统的研究与优化对于提升客户满意度和忠诚度具有重要意义。系统通过收集和分析客户的购车历史、偏好和反馈，能够为客户提供个性化的购车建议和方案，使客户享受到更加便捷、高效的购车体验。同时，系统还能够提供全面的售后服务支持，包括保养提醒、故障报修等，进一步增强客户的忠诚度和品牌认同感。 <span class="hljs-keyword">Java </span>Web技术作为一种成熟且广泛应用的开发技术，具有高度的可定制性、可扩展性和安全性，非常适合用于构建满足现代汽配销售行业需求的管理系统。通过整合前端用户界面、后端业务逻辑和数据库存储等关键组件，<span class="hljs-keyword">Java </span>Web技术可以为企业提供一个功能强大、易于维护和升级的解决方案。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">汽配销售管理系统的优化升级对相关行业发展是至关重要的。随着市场变化，过去传统的汽配销售模式已经不能够满足需求，而新兴的数字化管理系统能够显著提升运行效率。故在现代市场中不断变化的需求中，选择使用新型数字化管理系统来降低企业成本，无疑是最明智的选择。此外，从客户体验来看，这类优化升级后的数字化管理系统，能够记录客户的购买记录和偏好，通过收集分析客户的购买历史，针对性提供个性化的购物推荐方案，让客户明显察觉出选购过程更加便捷。同时，此类系统往往还提供完善的售后服务功能，如配件保养提醒、维修指导实用方案等，这大幅度提升了客户满意度。从技术实现方面看，采用成熟的主流开发框架，能够更加便捷地构建满足现代汽配销售行业需求的管理系统。这种技术方案在满足房前业务需求的同时，最大限度保证了系统能够安稳运行，还便于后续的功能扩展以及维护升级。<br></code></pre></td></tr></table></figure>

<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">随着科技的不断发展，汽配销售管理系统也在不断地完善和优化。在国外许多先进的汽配销售管理系统已经投入实际应用，为汽配销售行业带来了极大的便利。例如美国的汽配销售管理系统采用了大数据和人工智能技术，可以根据消费者的购车需求和喜好，为他们推荐最合适的汽车配件型号和配置。此外德国的汽配销售管理系统还具有很强的售后服务功能，可以为消费者提供详细的保养和维修建议，提高消费者的满意度。 在国内随着汽车市场的不断扩大和竞争的加剧，越来越多的汽配销售企业开始关注汽配销售管理系统的研究与开发。目前国内的一些大型汽配销售企业已经开始尝试引入先进的汽配销售管理系统，以提高销售效率和客户满意度。然而由于国内汽配销售行业的快速发展和技术水平的不足，许多企业在引入汽配销售管理系统时仍然面临着许多挑战。因此国内的汽配销售管理系统研究尚处于起步阶段，需要不断地进行技术创新和完善。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">当前，汽配销售管理系统在国内外都取得了显著发展。国外先进系统比如美国的智能推荐系统，采用智能推荐技术，能根据车主需求自动匹配配件，给用户提供个性化购买建议。而德国的系统则专注于更完善的售后服务以及专业保养，还提供维修指导详细实用方案。相比之下，国内的汽配销售管理系统尽管起步较晚，但当前已经有大型企业开始使用此类管理系统，用来帮助提升销售效率以及改善服务质量。不过，由于汽配行业发展迅速而相关技术累计不充分，国内的系统应用在投入市场后仍面临着诸多挑战。总体来看，国内汽配销售管理系统还处于发展初期，在智能化和售后服务等方面，仍有很大提升空间，需要继续改进技术和服务。<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql">本文围绕汽配销售管理系统的设计与实现展开研究，采用理论分析与工程实践相结合的方法，构建了一套完整的汽配行业数字化解决方案。本文各章节内容如下： 第<span class="hljs-number">1</span>章绪论从行业背景出发，分析了传统汽配销售模式在效率和管理方面的痛点，阐述了系统开发对推动行业数字化转型的重要意义。通过对比国内外汽配电商系统的发展现状，明确了本系统在提升运营效率、优化用户体验方面的研究价值，为后续研究奠定了理论基础。 第<span class="hljs-number">2</span>章相关技术重点介绍了系统开发采用的技术栈，包括SpringBoot框架的自动配置机制、MyBatis的动态<span class="hljs-keyword">SQL</span>特性以及MySQL数据库的事务支持能力。通过技术选型分析，验证了所选技术在实现高并发交易、数据一致性等核心业务需求方面的适用性。 第<span class="hljs-number">3</span>章系统需求分析采用角色用例分析法，明确了消费者和管理员两类用户的核心需求。通过构建功能列表和原型设计，完善并实现了包括订单管理、商品管理等六大模块的系统功能架构。 第<span class="hljs-number">4</span>章总体设计从技术架构和功能模块两个维度展开，提出了基于SpringBoot<span class="hljs-operator">+</span>Vue的前后端分离架构方案。通过数据库ER图和类关系图设计，构建了包含<span class="hljs-number">19</span>张核心数据表的数据库模型，形成了覆盖汽配销售全流程的系统级设计方案。 第<span class="hljs-number">5</span>章详细设计与实现聚焦系统核心功能模块，采用类图、时序图和流程图为用户登录、选购下单、订单管理等关键业务提供了详细的实现方案。通过代码片段和数据库表结构说明，展示了系统在库存预占、支付回调等业务场景中的具体处理逻辑。 第<span class="hljs-number">6</span>章系统测试设计了完整的测试方案，通过多维度验证系统可靠性，特别针对高并发下单、库存一致性等关键场景进行压力测试，确保系统在业务高峰期的稳定表现。 第<span class="hljs-number">7</span>章结论总结了系统在提升汽配企业运营效率、优化客户服务体验方面取得的成果，分析了当前实现的局限性，并从智能推荐算法完善方面提出了未来改进方向。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs">由于传统的汽配销售行业可能带来一系列问题，如效率低下、管理粗放等，故本论文以此为切入点，采用理论与实践相结合的方法，深入研究汽配销售管理系统的设计与实现。本论文各章节主要内容如下：<br>第1章是绪论部分，首先描述了汽配行业现状，指出传统销售模式可能会带来效率或管理方面的问题，以此为论据说明了开发本系统对推动汽配行业发展具有重大作用。后续对比了国内外汽配电商系统的发展现状，进一步明确了本系统确实能极大提升并改善用户体验。<br>第2章是相关技术，这部分内容详细介绍了本系统开发过程中采用的主流技术栈，其中重点分析了SpringBoot框架、Mybatis框架和MySQL数据库，这些核心技术栈极大了提升系统开发效率。<br>第3章是系统需求分析，分别从前台商城和后台管理的角度规划出该系统的核心功能模块，其中重点剖析了用户登录、选购下单和订单管理流程，还通过可行性分析验证了该系统在经济、操作和技术层面的可行性。<br>第4章是总体设计，通过系统分析本系统的技术架构和功能模块，完成了系统的总体设计方案，同时基于业务需求建立了较为完整的数据库模型和类结构设计。<br>第5章是详细设计与实现，分别对用户登录、选购下单和订单管理三大核心功能进行了全面的详细设计，通过类图、时序图、流程图和数据库表设计，系统性阐述了各功能模块的业务逻辑与实现。<br>第6章是系统测试，主要针对用户登录、用户选购下单和商品管理功能进行测试，通过设计更全面的测试用例，模拟真实用户操作流程，尽可能覆盖汽配销售环节中多个业务场景。<br>第7章是结论，简要总结了该系统使用什么样的技术解决了何种难题，同时指出了目前该系统仍有诸多功能待持续完善，包括技术选型优化和功能扩展等方面。<br></code></pre></td></tr></table></figure>

<figure class="highlight lasso"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs lasso">该框架提供了各种现成的功能模块（如安全认证、数据库连接等），开发者只需简单配置就能快速搭建系统骨架。<br>在本项目中，该框架主要负责处理用户请求、业务逻辑和系统间的协调工作。<br>通过自动配置机制，SpringBoot能根据项目依赖自动装配所需组件，大幅减少传统Spring框架繁琐的<span class="hljs-built_in">XML</span>配置工作。<br>该框架内置了Tomcat服务器，无需额外部署即可运行项目，一键自动配置常用功能。<br>SpringBoot框架还提供了完善的监控端点，可以实时查看应用健康状态、性能指标等信息，极大方便了系统运维。<br>同时，该框架的starter机制使依赖管理更加简单，只需引入相应starter包即可获得完整功能支持。<br>SpringBoot框架的重要优势是生态丰富。有成千上万的扩展库可以选择，轻松集成本项目用到的MyBatis、Redis等。<br>在微服务架构下，SpringBoot与Spring Cloud完美配合，可以快速构建分布式系统。<br>此外，该框架的自动错误处理机制能捕获并记录，配合统一的日志系统，让问题排查更加便捷。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs scss">相较于Spring框架，SpringBoot框架提供了自动化配置，这大大简化了项目的配置过程。通过约定优于配置的原则，很多常用的配置可以自动完成，开发者可以专注于业务逻辑的实现。<br>SpringBoot框架还提供了快速的项目启动器，其中默认集成了多种内嵌服务器(如Tomcat、Jetty、Undertow)，无需额外配置，即可将应用打包成可执行的JAR文件，方便部署和运行。<br>SpringBoot通过自动配置功能，根据项目中的依赖关系和约定俗成的规则来配置应用程序，减少了配置的复杂性，使开发者更容易实现应用的最佳实践。通过引入不同的Starter，可以快速集成常用的框架和库(如数据库、消息队列、Web开发等)，极大地提高了开发效率。<br></code></pre></td></tr></table></figure>

<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql">本章详细分析了系统开发过程中使用的核心技术。SpringBoot框架作为系统基础，通过其自动配置和starter机制简化了开发流程，内置的安全组件为登录认证提供了可靠支持。MyBatis框架作为持久层解决方案，其动态<span class="hljs-keyword">SQL</span>特性满足了商品多条件查询需求，二级缓存机制显著提升了数据访问效率。MySQL数据库凭借其稳定的事务特性和索引优化策略，为订单管理等核心业务提供了高效的数据存储支持。这三大核心技术构成了系统稳定运行的技术基石，保证了系统性能和可维护性。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql">本章重点介绍了系统开发中用到的几个关键技术。SpringBoot作为本系统开发的基础框架，简化了项目的搭建和配置，其内置了安全功能让用户注册登录和权限管理更加方便。Mybatis作为成熟的ORM框架，相较于传统的JDBC技术，极大程度减少了繁琐的配置，提升编码效率，还支持灵活地编写<span class="hljs-keyword">SQL</span>语句，满足业务场景中多种复杂需求。MySQL作为系统的数据库，支持高效的数据存储和较为完备的事务处理机制，在业务场景中还能通过<span class="hljs-keyword">SQL</span>调优（如索引优化，分库分表等）大幅提高查询效率。这三大核心技术是本系统稳定运行的关键，同时系统的性能和可维护性也得到了保证。<br></code></pre></td></tr></table></figure>

<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">首先，从经济可行性来看，该系统具有显著投资价值。开发成本主要包括硬件设备采购和软件开发投入，而预期收益则来源于线上销售额增长、广告收入提升等多个方面。投资回报分析显示，系统可在合理周期内收回成本并实现盈利，为汽配销售企业创造可观的经济效益。 其次，操作界面简洁可观。前台采用直观的交互界面，使消费者能够便捷完成商品浏览、下单支付等操作；后台管理系统通过明确的权限设置和操作帮助管理员高效处理商品管理、订单处理等工作。这种双端优化设计确保了系统的易用性。 再次，技术可行性已得到充分验证。基于SpringBoot框架的开发方案，不仅能够快速实现系统核心功能，还能无缝集成MyBatis、MySQL等成熟技术。系统架构支持高并发访问和稳定运行，完全满足汽配销售业务的性能要求。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs">从经济层面来看，开发这样的系统需要一定的硬件和软件投入，考虑到系统上线后能带来更多线上订单和广告收入，预计能在可接收时间范围内回本并盈利，这对传统的汽配销售企业来说是个不错的投资。<br>从操作层面来看，本系统的前台商城界面简单清晰，方便消费者浏览汽配商品详情信息和选购下单，而后台管理系统则实现了明确的权限划分，后台管理员能够轻松管理在售商品信息，跟踪订单流水，大幅提升工作效率。<br>从技术层面看，本系统采用了成熟的开发框架和数据库技术，在保证系统能稳定运行的同时，还支持大量用户同时访问，完全能满足当今汽配销售行业的业务需求。<br>以上我们分别从经济层面、操作层面和技术层面出发，探究该系统的可行性，探究结果表明本系统成本可控，操作方便，技术可靠，是一个值得投入的项目。<br></code></pre></td></tr></table></figure>

<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">本系统功能架构划分为六大核心模块：用户管理、选购下单、订单管理、商品管理、营销管理和权限管理。其中，选购下单与订单管理作为系统的关键功能模块，具有复杂的业务逻辑和紧密的交互关系，其详细用例将在后续章节进行深入分析。 这些功能模块相互衔接，形成了完整的汽配销售业务闭环：前台为用户提供高效的汽配商品购买体验，后台则为汽配厂商提供运营管理支持。后续内容将着重剖析选购下单和订单管理这两个核心模块的具体实现方案。基于上述分析，系统整体用例图如图3<span class="hljs-string">-1</span>所示。用户管理功能如表3<span class="hljs-string">-1</span>所示。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs subunit">本系统主要由六大功能模块组成，包括用户管理、商品选购、订单管理、商品管理促销活动和权限管理。其中商品选购和订单管理是最核心的功能模块，其中设计的业务流程较为复杂，将在后续详细介绍它们的具体实现方式。<br>这些功能模块间相互配合，共同构成了完整的汽配销售管理系统。前台商城让顾客浏览选购汽配商品更加便捷，后台管理使得管理员轻松管理在售商品信息，大幅提高工作效率。在接下来的内容中，将重点介绍商品选购下单和订单管理这两个核心模块的具体设计方案。基于上述分析，系统整体功能结构如图3<span class="hljs-string">-1</span>所示，用户管理具体功能说明见表3<span class="hljs-string">-1</span>。<br></code></pre></td></tr></table></figure>

<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">在汽配销售场景中，当消费者进入汽配销售系统时，通常已对所需配件的型号、规格等参数有清晰认知，因此系统需要提供精准的商品检索和匹配功能。本系统的选购下单模块通过智能搜索和精准推荐相结合的方式，帮助消费者快速定位目标商品。 选购下单模块的核心业务流程表现为：消费者通过搜索或分类导航找到目标商品后，系统实时展示库存状态和价格信息，并支持按品牌、型号等关键参数进行筛选；消费者确认所需商品的规格和数量后，系统自动生成包含完整商品信息的待支付订单；订单支付流程完成后触发库存扣减机制。这一流程实现了从选购到下单的无缝衔接，同时保障支付和订单信息的安全可靠。基于上述分析，选购下单用例图如图3<span class="hljs-string">-2</span>所示。选购下单功能如表3<span class="hljs-string">-5</span>所示。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs subunit">在汽配商品销售过程中，顾客通常已经知道自己需要什么样型号的配件，因此，系统必须具备准确检索和匹配商品的功能。在本系统的选购下单功能模块中，通过实现智能搜索以及精准推荐，帮助顾客快速找到想要的商品。<br>具体购买流程如下：顾客通过搜索或分类查找商品时，系统会立即显示库存情况和价格信息，此时顾客可以按品牌、型号等条件筛选商品。选定商品规格和数量后，系统会自动生成待支付的订单。在完成支付后，系统会自动扣除相应库存。整个选购下单流程从商品选购到下单一气呵成，还确保了支付安全和订单信息安全可靠。选购下单用例图如图3<span class="hljs-string">-2</span>所示，具体功能说明如表3<span class="hljs-string">-5</span>所示。<br></code></pre></td></tr></table></figure>

<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">当消费者完成支付流程后，订单即进入系统管理阶段，成为可被全程跟踪的系统订单。订单管理模块主要业务包括订单处理、物流跟踪及售后服务。 用户下单并提交订单后进入待付款状态；支付成功后，订单转为待发货状态，若超时未支付则自动关闭。商家确认订单后填写物流信息并发货，订单状态更新为已发货，同时系统同步物流轨迹供用户实时跟踪。物流签收后，用户可手动确认收货或由系统在超时后自动完成，订单状态标记为已完成。若发生退货、退款等售后问题，订单可能变更为无效订单或逻辑删除。整个流程覆盖了订单生命周期中的关键环节，并与支付、库存、物流等系统紧密协同，保障交易顺畅与用户体验。基于上述分析，订单管理用例图如图3<span class="hljs-string">-3</span>所示。订单管理功能如表3<span class="hljs-string">-6</span>所示。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">订单管理模块的实现主要涉及到订单状态变化：基于上述选购下单流程，在顾客成功下单后，订单显示待付款。顾客付款成功后，订单状态变为代发货，而商家确认订单并发货后，更新订单状态为已发货，此时顾客可查看到物流信息。在顾客嘴最终收货并确认后，订单状态标记为已完成。整个工作流程中可能出现一些特殊情况，比如顾客选购下单后超时未付款，则订单自动取消；顾客在收货确认后需要退换货，订单则转为售后处理状态，后续由商家进一步跟进。以上流程基本覆盖了订单生命周期中的各个关键环节，自动更新库存，同步物流信息，处理退款售后等问题，整个流程确保了从下单到收货的每个环节都能被有效跟踪和监测管理。订单管理用例图如图3<span class="hljs-string">-3</span>所示，具体功能说明如表3<span class="hljs-string">-6</span>所示。<br></code></pre></td></tr></table></figure>

<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">安全性：系统应实现完善的数据加密机制和基于角色的权限控制，确保用户信息和交易数据安全。 可扩展性：采用模块化架构设计，支持汽配品类和业务功能的灵活扩展，便于后期功能升级。 易用性：系统界面设计应符合汽配行业特点，操作流程简洁明了，确保消费者和管理员都能快速上手使用。 适应性：基于SpringBoot框架开发，具有良好的跨平台特性，能够适配各类操作系统和硬件环境。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs">系统设计需要满足以下关键要求：<br>从安全保护方面来看，本系统应该采用完备的数据加密技术，避免数据传输过程中的可能出现的监听和窃取安全问题；同时设置不同的账号权限，谨防登录信息伪造等问题，确保用户隐私安全和数据信息安全。<br>从扩展能力方面来看，本系统应采用模块化设计，在设计初期应该通过广泛地调研分析，充分考虑到后续开发完善过程中的可扩展点，比如增加新的商品种类，支持新的支付方式等。<br>从使用体验方面来看，本系统前台商城界面和后台管理界面都应该做到简单直观，操作步骤清晰明确，让顾客和管理员都能快速上手使用。<br>从兼容性能方面来看，本系统应该要基于主流开发框架实现，提供的终端要适配不同品牌的电脑和手机，还要具备一定的跨平台性，以支持多种操作系统。<br></code></pre></td></tr></table></figure>

<figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs armasm">汽配销售管理系统在技术层面采用分层架构设计，基础环境基于JDK1.<span class="hljs-number">8</span>开发平台，配合IDEA、HBuilder和Navicat等开发工具；后端以SpringBoot为核心框架，集成SpringSecurity实现认证授权，MyBatis处理数据持久化，Elasticsearch提供搜索服务，同时结合Druid连接池、JWT令牌等组件；终端支持<span class="hljs-built_in">PC</span>浏览器和移动端访问，整体架构通过Nginx实现负载均衡，采用Docker容器化部署，形成了一套完整的前后端分离技术方案。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs armasm">本汽配销售管理系统采用分层架构设计，主要技术方案包括：使用Java1.<span class="hljs-number">8</span>开发平台，配套的开发工具包括但不限于IDEA、HBuilder和Navicat等。同时，整个系统基于主流开发框架SpringBoot开发，这其中集成Security模块实现安全认证，集成Mybatis框架实现高效数据库操作，集成Elasticsearch实现商品检索，此外还集成了数据库连接池以及JWT身份验证令牌等组件。本系统通过Niginx实现流量分发，采用Dokcer实现容器部署，终端还支持<span class="hljs-built_in">PC</span>端、移动端访问。整体采用前后端分离的技术架构。<br></code></pre></td></tr></table></figure>

<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">汽配销售管理系统的架构设计是项目开发的关键环节，其核心在于构建前后端分离的双平台体系。本系统采用SpringBoot+MyBatis技术栈实现，通过Docker容器化技术确保部署的灵活性和可扩展性。前台商城系统展示了汽配商品的门户首页，支持多条件筛选搜索商品，提供完整的购物车结算和订单处理等功能。后台管理系统提供了全生命周期的商品管理、基于角色权限控制体系管理以及完善的订单跟踪等功能。以上是汽配销售管理系统的主要功能需求，通过这些功能的设计和实现，为用户提供更加便捷、快速、安全的汽配销售服务。该系统功能结构设计如图4<span class="hljs-string">-1</span>所示：<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">汽配销售系统采用前后端分离的设计方案，主要包括两个部分：前台商城面向广大消费者，主要展示汽配商品详情信息，支持多种条件筛选商品，还提供了购物车下单、订单结算以及物流跟踪等功能；后台管理则面向商家，后台管理员可管理商品上下架，设置不同员工的操作权限，跟踪并处理订单流水。总的来说，本系统采用主流开发技术，使用Docker实现容器部署，确保了系统能稳定运行并方便扩展。通过这样的功能设计，为用户提供了便捷且安全的汽配商品购买体验。本系统功能结构设计如图4<span class="hljs-string">-1</span>所示。<br></code></pre></td></tr></table></figure>

<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pgsql">汽配销售管理系统中的各个类与类之间的关系如图 <span class="hljs-number">4</span><span class="hljs-number">-3</span>所示。 该类关系图展现了严谨的面向对象设计架构。以<span class="hljs-keyword">User</span>类为核心的用户中心模块通过聚合关系绑定<span class="hljs-keyword">Role</span>类，形成基于角色的访问控制体系，<span class="hljs-keyword">Role</span>类进一步组合Permission类实现细粒度的权限管理。LoginLog类记录用户登录行为，与<span class="hljs-keyword">User</span>形成关联关系，确保操作可追溯。商品管理模块以Product类为主体，聚合Brand和Category类构建商品分类体系，组合ProductAttribute类实现商品特性扩展。订单处理模块通过<span class="hljs-keyword">Order</span>类作为业务聚合根，严格组合OrderItem类管理订单明细，关联OrderDelivery类处理物流信息，组合PaymentInfo类保障交易完整性。OrderLog类记录订单状态变更，与<span class="hljs-keyword">Order</span>形成操作审计关系。系统巧妙运用多种关系类型：<span class="hljs-keyword">User</span>与<span class="hljs-keyword">Order</span>的关联体现业务交互，Product与OrderItem的关联实现商品销售，Category的自关联支持多级分类。各类均封装核心业务属性与方法，如<span class="hljs-keyword">User</span>的登录验证、Product的库存管理、<span class="hljs-keyword">Order</span>的状态转换、PaymentInfo的支付处理等，共同构建了完整的汽配销售业务领域模型。类间关系设计合理的关联实现了模块间协同，充分体现了高内聚低耦合的设计思想。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pgsql">汽配销售管理系统的类结构设计如图<span class="hljs-number">4</span><span class="hljs-number">-3</span>所示，主要包含以下核心模块及其相互关系。在用户管理模块中，用户（<span class="hljs-keyword">User</span>）与角色（<span class="hljs-keyword">Role</span>）关联，实现了权限控制。同时角色（<span class="hljs-keyword">Role</span>）包含多个具体权限（Permission），而登录记录（Loginlog）则用来跟踪并记录用户操作。在商品管理模块中，商品（Product）关联品牌（Brand）和分类（Category），商品属性（ProductAttribute）则负责描述商品特性，此外分类（Category）还支持多级子分类。在订单管理模块中，订单（<span class="hljs-keyword">Order</span>）包含多个订单项（OrderItem），同时关联物流（OrderDelivery）和支付信息（PaymentInfo）等，而订单日志（OrderLog）则用来跟踪订单流水并记录订单状态变更。总的来说，各模块之间通过合理的关联关系实现业务协作，用户（<span class="hljs-keyword">User</span>）可以创建多个订单（<span class="hljs-keyword">Order</span>），商品（Product）通过订单项（OrderItem）参与汽配商品销售，此外还参与到本系统的自动处理库存、下单支付等业务流程中。这样的类间关系设计，体现了高内聚低耦合的设计思维，还使得本系统各模块既能独立运作，又能协同工作，确保销售业务流畅运行。<br></code></pre></td></tr></table></figure>

<figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs armasm">用户登录模块包含用户认证、权限验证和日志记录，涉及到的类有用户类、角色类、权限类和登录日志类。用户类中除了基本的属性如username、password和status外，还包含checkPassword方法用于验证用户输入的密码是否与存储的加密。角色类通过hasPermission方法验证用户是否拥有特定权限，addPermission方法用于动态添加权限。权限类通过isApiPermission方法判断权限类型，getPermission方法生成完整的权限标识。登录日志类中的createSuccessLog静态方法用于快速创建成功登录日志记录，自动填充<span class="hljs-built_in">IP</span>、设备和时间等信息。用户类关联多个角色类形成用户-角色关系，角色类关联多个权限类构成角色-权限映射，用户类与登录日志类形成一对多的登录记录关系，共同完成从用户认证到权限控制的完整流程。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pgsql">用户登录模块主要由以下几个部分组成。其中用户信息（<span class="hljs-keyword">User</span>）包含用户名、密码、状态等基本信息，此外还提供了登录过程中的密码验证功能。在角色管理（<span class="hljs-keyword">Role</span>）中，系统会在不同的操作环节检查用户是否具有某项权限，此外还支持管理员动态添加新的角色权限。在权限控制（Permission）中，主要用来区分不同类型的权限，并借此依次生成完整的权限标识，用以保证系统操作过程中的安全可靠。最后在登录记录（LoginLog）中，系统自动记录了登录IP、设备、时间等信息，区分成功和失败的登录尝试。这些部分之间的关系体现在一个用户可以拥有多个角色，而一个角色可以包含多个权限，此外一个用户还会产生多条登录记录。所以用户登录的整个流程可以总结为，用户在登录界面输入账号密码登录后，系统验证密码并检查权限，记录本次登录信息，并根据权限决定该用户可访问的功能。<br></code></pre></td></tr></table></figure>

<figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs armasm">用户登录模块中相关的数据库表包含用户表、角色表、权限表、用户角色关联表、角色权限关联表以及登录日志表。通过用户表中的用户状态字段与角色权限体系建立连接，在用户登录时进行多层级验证，包括密码校验、账户状态检查和权限加载。登录日志表记录了每次登录的详细上下文信息，包括<span class="hljs-built_in">IP</span>地址、设备类型和操作结果。用户通过角色关联权限、权限表中的权限编码字段与前端菜单及接口权限绑定，形成完整的访问控制链。数据库表结构中，用户表存储加密后的密码和盐值，角色表定义数据权限范围，权限表标记资源类型和操作标识，关联表维护多对多关系，登录日志表实现审计追踪，各表通过外键约束确保数据一致性，共同实现从身份认证到权限管理的全流程。用户表如表<span class="hljs-number">5</span>-<span class="hljs-number">1</span>所示。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs armasm">用户登录模块涉及到的数据库表包括以下库表。在用户表中存储了用户账号、加密密码等信息，同时记录登录用户账号状态，判断其是否能正常使用。在角色表中定义了不同角色的权限范围，如管理员、普通用户等。在权限表中记录了本系统可访问的菜单和功能，每种权限都对应有唯一编码。在关联表中保存了用户和角色的对应关系，以及角色与权限的对应关系。在登录日志表中记录了每次登录的<span class="hljs-built_in">IP</span>、设备、操作结果和地址等信息，同时保存登录成功和失败信息。在整个登录验证流程中，检查用户名和密码是否正确，确认该账号是否可用，加载用户拥有的角色和权限，最后记录本次登录信息。这些库表通过相互关联，共同实现了账号安全保护，权限的分级管理以及操作记录追踪。用户表具体结构如表<span class="hljs-number">5</span>-<span class="hljs-number">1</span>所示。<br></code></pre></td></tr></table></figure>

<figure class="highlight elm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs elm">商品选购下单模块的数据库设计包含品牌管理、商品信息、分类体系、订单交易、购物车和评价系统，涉及的核心表包括品牌表、商品信息表商品所属分类表、订单表以及商品评价表。品牌表通过id和name字段维护品牌基础信息，商品信息表以brand_id和product_category_id关联品牌与分类，并包含publish_status和promotion_<span class="hljs-keyword">type</span>字段管理上下架及促销状态。订单表通过member_id关联用户，status字段标记订单生命周期，购物车表冗余存储product_brand和product_category_id确保数据一致性，商品评价表通过star和pics字段实现多维度的评价展示。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">商品选购下单模块的数据库设计主要包含以下几个部分。在商品信息相关表中，品牌表记录了商品关联的品牌信息，包括品牌logo、品牌描述和品牌故事等；商品表则记录了商品详情信息，包括商品描述、价格、库存、所属分类等；商品分类表则用来管理商品分类，记录了多级商品所属分类类型。在订单相关表中，订单表记录了用户下单信息，包括选购商品信息、下单用户信息以及收货地址等；而购物车表则负责暂存用户想要购买的商品，在下单支付后清除购相关物车信息。在商品评价系统中，主要由评价表保存用户评分以及评价内容。各表之间，商品关联到所属品牌和分类，订单关联到用户和选购商品，评价则关联到订单和商品详情。<br></code></pre></td></tr></table></figure>

<figure class="highlight fortran"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs fortran">订单管理模块围绕订单主类展开，关联订单明细类、物流信息类和操作日志类。订单主类通过<span class="hljs-keyword">status</span>状态标记推动业务进行，其中cancel方法处理取消逻辑并触发库存释放，confirmReceive方法完成收货确认。订单明细类通过productName和price等快照字段保留交易时商品状态，物流信息类依赖track方法实时查询物流轨迹，操作日志类记录所有关键操作。类详细设计如图<span class="hljs-number">5</span>-<span class="hljs-number">7</span>所示。 订单管理模块的数据库设计围绕订单表展开，通过订单明细表记录商品快照信息，物流信息表跟踪配送状态，操作日志表审计关键操作。订单表通过order_sn保证业务唯一性，并关联user_id标记用户归属；订单明细表通过order_id外联主订单，保留product_name和快照数据确保历史订单不受商品变更影响；物流信息表记录delivery_company和delivery_sn实现物流追踪；操作日志表通过<span class="hljs-keyword">action</span>字段（如支付/取消）和operator记录操作轨迹。所有表均包含create_time实现时间维度追溯，退货申请表作为扩展支持售后流程，形成从订单创建、状态变更到最终完结的完整流程。订单表如表<span class="hljs-number">5</span>-<span class="hljs-number">12</span>所示。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">订单管理模块主要包含以下功能。在订单处理流程中，主要涉及到订单流转和订单状态管理，如待付款、已发货、已完成等，除此之外，还提供了用户取消订单时自动回复库存的功能，以及用户确认收货功能。在订单信息记录中，保存了订单流转过程中的商品商品信息，如名称、价格等，记录了物流配送信息，还支持订单操作记录跟踪功能，如订单支付、订单取消等。故在订单管理相关数据库设计中，订单主表用来记录订单基本信息，订单商品表保存了购买时的商品详情，物流信息表记录了跟踪配送状态，操作记录表则记录了订单流转过程中的所有重要操作。在以上整个操作流程中，每个订单都有唯一编号，订单内的商品信息不受后期改动影响，用户可以实时查询物流状态，后台管理完整记录了订单全流程操作，此外还支持退货退款等售后服务。订单表如表5<span class="hljs-string">-12</span>所示。<br></code></pre></td></tr></table></figure>

<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">用户登录、选购下单和订单管理三大功能模块构成了汽配销售管理系统的核心业务架构。本章节以这三个关键模块为切入点，对系统的核心功能进行了全面的详细设计。通过类图、时序图、流程图和数据库表设计等多维度建模方式，系统性地阐述了各模块的业务逻辑与数据关系。其中，类图明确了实体间的结构关系，时序图规范了服务间的调用流程，流程图梳理了业务状态流转，数据库表设计严格遵循ACID原则保证数据准确可靠。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">汽配销售管理系统的核心功能主要包括用户登录、选购下单和订单管理三大模块，本章详细介绍了这些功能的设计方案。使用类图展示了各功能模块的组成结构，使用时序图说明了系统各部分的交互过程，使用流程图描述了核心业务处理步骤，还是用数据库设计确保了数据准确安全。经过详细设计与实现，整个系统实现了清晰的模块划分、规范的交互流程、完整的业务处理逻辑以及可靠的数据存储方案，能帮助用户顺畅完成心仪商品的选购下单，同时也有利于管理员高效处理订单流水。<br></code></pre></td></tr></table></figure>

<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">此功能测试包括几个方面：功能性测试需覆盖正常登录流程、异常输入校验（包括空用户名、空密码、错误凭证等）、密码加密存储与传输机制，以及登录失败次数限制等安全策略；性能测试需验证系统在并发用户登录场景下的响应速度、资源占用情况，确保登录接口在高负载下仍能保持稳定；安全性测试则重点检测SQL注入、XSS攻击等常见安全威胁的防护能力。具体测试内容如下： (1)用户登录测试。测试用例如表6<span class="hljs-string">-1</span>所示，测试界面如图6<span class="hljs-string">-1</span>所示。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs subunit">登录功能测试主要包括以下几个方面：测试用户能够正常登录系统，包括输入正确的用户名和密码时能否成功登录，登录后能否正常跳转到系统首页，能否正常使用系统各项功能；测试异常登录情况处理，包括输入错误的用户名或密码时是否提示正确的错误信息，不输入用户名或密码时是否提示必填信息，以及连续多次输入错误密码后账户是否会被锁定；测试多用户同时登录时，系统能够同时处理多个用户登录请求，登录响应时间是否在合理范围内，以及服务器资源是否使用正常。具体测试内容如下： (1)用户登录测试。测试用例如表6<span class="hljs-string">-1</span>所示，测试界面如图6<span class="hljs-string">-1</span>所示。<br></code></pre></td></tr></table></figure>

<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">此功能测试包括几个方面：功能性测试需覆盖商品基础信息管理（包括上架、修改、删除等操作），重点验证必填项校验、格式规范检查、品牌<span class="hljs-regexp">/分类关联性等核心业务规则；流程完整性测试需检测商品信息变更后的数据同步机制，包括前后台数据一致性模块（如库存/</span>订单）的联动更新；性能测试则需评估批量商品信息调整效率，以及高并发访问时的系统稳定性。具体测试内容如下： (<span class="hljs-number">1</span>)商品上架测试。测试用例如表<span class="hljs-number">6</span>-<span class="hljs-number">6</span>所示，测试界面如图<span class="hljs-number">6</span>-<span class="hljs-number">6</span>所示。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">商品管理功能测试主要包括以下几个方面：测试商品上架时，检查商品信息能够正常录入，验证必填信息未填时是否提示错误，测试商品图片上传和展示功能，以及检查商品分类和相关品牌选择是否准确关联；测试商品信息修改时，验证修改商品价格、库存等关键信息后是否生效，检查修改后的商品在前台页面是否正确显示，测试特殊字符输入时的处理；测试商品下架时，检查下架商品是否从前台页面消失，验证已下架的商品在订单中的处理情况，测试下架商品重新上架的功能是否完善。除此之外，还需测试商品信息修改后前台页面是否及时更新，以及库存变动后相关订单能都正确处理等。<br></code></pre></td></tr></table></figure>

<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">本章对汽配销售管理系统进行了全面的功能测试和性能验证重点测试了用户认证、商品库存管理、订单状态流转等核心功能模块，验证了系统在业务流程上的正确性和完整性。同时采用压力测试工具对高并发场景下的系统，包括商品查询、订单创建和支付处理等关键环节，特别加强了数据安全和防刷单机制的专项测试。通过模拟真实用户操作流程，确保系统符合业务需求和技术规范。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">本章重点测试了汽配销售管理系统的三个核心模块。在用户登录功能测试中，测试用户能否正常登录以及异常登录情况时的处理。在选购下单功能测试中，测试商品搜索筛选、购物车选购、订单创建以及支付等功能的完整性。在商品管理功能测试中，测试商品上下架流程、商品信息修改以及批量处理等。通过模拟真实的用户操作，确保了本系统更加安全可靠，购物流程和商品管理更加便捷顺畅。<br></code></pre></td></tr></table></figure>

<figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs armasm">本文基于Spring Boot框架设计并实现了一套完整的汽配销售管理系统，主要完成了以下工作：首先，通过系统化的需求调研与分析，设计了涵盖用户关系管理、汽配商品生命周期管理和交易流程管理等核心业务模块的体系架构；其次，采用MyBatis持久层框架实现了<span class="hljs-number">19</span>张核心数据表的CRUD操作，并运用Redis缓存技术优化了商品查询性能；最后，通过前后端分离的开发模式，完成了包含<span class="hljs-built_in">PC</span>端和移动端的多终端适配方案。系统配销售全流程的数字化管理，包括商品展示、在线交易、选购下单、订单跟踪等核心业务功能，经测试验证可支持<span class="hljs-number">500</span>+TPS的高并发访问。 然而，系统仍存在以下待改进之处：在功能层面，当前版本尚未实现智能推荐和供应商协同等扩展功能；在技术层面，分布式事务处理机制有待优化，以应对更复杂的业务场景。未来计划引入机器学习算法优化商品推荐功能，并探索微服务架构改造以提升系统的可扩展性。本系统的设计与实现为汽配行业的数字化转型提供了一个可行的技术解决方案，其架构设计思路也可为同类系统的开发提供参考。<br></code></pre></td></tr></table></figure>

<p>修改：</p>
<figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs armasm">本汽配销售管理系统基于SpringBoot框架开发，结合MySQL数据库和Mybatis等技术，实现了三大核心功能。在用户管理功能模块，系统支持安全登录和权限控制，不同的角色享有权限各不相同，可操作不同的功能。在选购下单功能模块，前台商城提供了商品搜索、商品详情信息浏览、选购下单以及在在线支付等功能，后台管理则支持在售商品管理以及订单流水监控等核心功能。总体看来，本系统操作简单，界面清晰，数据处理快速稳定，且支持跨平台和多端（<span class="hljs-built_in">PC</span>端/移动端）访问。<br>当然，系统仍有待改进之处，已经暴露出的问题包括但不限于：前端商城商品图片加载速度不稳定，有时较缓慢；促销活动模块较为单一，目前仅支持少数促销活动；缺少智能推荐商品功能；后台管理系统中，订单统计报表不够直观。由于本系统设计局限性以及时间关系，计划在未来不断优化和改进该系统中存在的问题，全面考虑系统可扩展点，从更复杂的业务场景出发，采用前沿技术不断拓展优化系统设计，最大程度提升用户体验，使得该系统在当今汽配销售行业中更能发挥重大作用。<br></code></pre></td></tr></table></figure>

<blockquote>
<p>2025 年 4 月 21 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://qimingzhihui.chachongz.com/">启明智汇 (chachongz.com)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250421122839799.png" alt="image-20250421122839799"></p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs makefile"><span class="hljs-section">卡号：11036487928805360:820400</span><br></code></pre></td></tr></table></figure>

<figure class="highlight less"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs less">论文查重券】的使用方法：<br><span class="hljs-number">1</span>、电脑登录启明智汇查重官网<br><span class="hljs-selector-tag">https</span>:<span class="hljs-comment">//qimingzhihui.chachongz.com/</span><br><span class="hljs-number">2</span>、选择<span class="hljs-selector-tag">CopyCheck</span>检测系统<br><span class="hljs-number">3</span>、输入<span class="hljs-selector-attr">[论文标题]</span>、<span class="hljs-selector-attr">[作者]</span>、<span class="hljs-selector-attr">[上传文件]</span><br><span class="hljs-number">4</span>、<span class="hljs-selector-attr">[支付方式]</span>选择［检测卡］<br><span class="hljs-number">5</span>、输入检测卡卡号、卡密检测<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250421124206959.png" alt="image-20250421124206959"></p>
<p>特么卡内无余额。。</p>
<p><a target="_blank" rel="noopener" href="https://www.paperpass.com/panel/index">新论文检测_PaperPass 论文检测</a></p>
<p><a target="_blank" rel="noopener" href="https://www.paperred.com/report/center/check">查重报告 - PaperRed 免费论文查重</a></p>
<p>艹，今天有的受了。。</p>
<p><a target="_blank" rel="noopener" href="https://www.paperpass.com/panel/report?page=1">查看报告_PaperPass 论文检测</a></p>
<p>改写和重写，18520 字。</p>
<h2 id="功能演示"><a href="#功能演示" class="headerlink" title="功能演示"></a>功能演示</h2><blockquote>
<p>2025 年 4 月 26 日</p>
</blockquote>
<p>终于给自己埋下坑了。</p>
<p>系统功能还是得稍作完善，毕竟四天后的预答辩要求演示系统功能，就是糊弄也得好好把系统跑起来才行。</p>
<img src="http://blog.memory-life.xyz/image-20250426123942146.png" alt="image-20250426123942146" style="zoom:150%;" />

<p>注册登录，测试完毕。</p>
<p>商品管理，优化商品属性，关联品牌，分类，图片上传。</p>
<p><img src="http://blog.memory-life.xyz/image-20250426162940179.png" alt="image-20250426162940179"></p>
<p><a target="_blank" rel="noopener" href="https://www.minio.org.cn/overview.shtml">MinIO | 企业级、高性能对象存储</a></p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs makefile">VMware Workstation 无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用的所有目录以及访问所有临时文件目录。<br><br><span class="hljs-section">未能将管道连接到虚拟机: 系统找不到指定的文件。</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://huaweicloud.csdn.net/670ce0f0e2ce0119e0a26f2c.html">VMware Workstation 无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用的所有目录以及访问所有临时文件目录。VMX 进程已经提前退出。_linux_sunnyyu519-华为开发者空间 (csdn.net)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_53143580/article/details/147002944">解决办法：VMware Workstation 无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用的所有目录以及访问所有临时文件目录-CSDN 博客</a></p>
<p>他妈还不信了。</p>
<p>重启未解决。。本地虚拟机启动失败确实在意料之外，优化其他功能吧。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">商品管理，营销管理，用户管理，系统管理，订单管理<br></code></pre></td></tr></table></figure>

<p>图片上传。</p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/mahmud/p/16931006.html">ElementUI 实现图片上传的功能 🌈~（已完成 ✔） - Mahmud(مەھمۇد) - 博客园 (cnblogs.com)</a></p>
<p>这部分具体研究，见七牛云章节。</p>
<p>批量设置新品，推荐，查询。</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs n1ql">Preparing: <span class="hljs-keyword">SELECT</span> p.* <span class="hljs-keyword">FROM</span> sms_home_new_product hp <span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span> pms_product p <span class="hljs-keyword">ON</span> hp.product_id = p.id <span class="hljs-keyword">WHERE</span> hp.recommend_status = <span class="hljs-number">1</span> <span class="hljs-keyword">AND</span> p.publish_status = <span class="hljs-number">1</span> <span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> hp.sort <span class="hljs-keyword">DESC</span> <span class="hljs-keyword">LIMIT</span> ?, ?;<br></code></pre></td></tr></table></figure>

<p>怎么还查这么个表，删掉。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs sql">delete_status                 <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;删除状态(0 - 未删除；1 - 已删除)&#x27;</span>,<br>publish_status                <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;上架状态(0 - 下架；1 - 上架)&#x27;</span>,<br>new_status                    <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;新品状态(0 - 不是新品；1 - 新品)&#x27;</span>,<br>recommand_status              <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;推荐状态(0 - 不推荐；1 - 推荐)&#x27;</span>,<br>verify_status                 <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;审核状态：0-&gt;未审核；1-&gt;审核通过&#x27;</span>,<br></code></pre></td></tr></table></figure>

<p>改写 SQL 语句，删除关联表。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-operator">&lt;</span><span class="hljs-keyword">select</span> id<span class="hljs-operator">=</span>&quot;getNewProductList&quot; resultMap<span class="hljs-operator">=</span>&quot;com.macro.mall.mapper.PmsProductMapper.BaseResultMap&quot;<span class="hljs-operator">&gt;</span><br>        <span class="hljs-keyword">SELECT</span> p.<span class="hljs-operator">*</span><br>        <span class="hljs-keyword">FROM</span> pms_product p<br>        <span class="hljs-keyword">WHERE</span> p.recommend_status <span class="hljs-operator">=</span> <span class="hljs-number">1</span><br>          <span class="hljs-keyword">AND</span> p.publish_status <span class="hljs-operator">=</span> <span class="hljs-number">1</span><br>        <span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> p.sort <span class="hljs-keyword">DESC</span><br>        LIMIT #&#123;<span class="hljs-keyword">offset</span>&#125;, #&#123;limit&#125;;<br>    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">select</span><span class="hljs-operator">&gt;</span><br></code></pre></td></tr></table></figure>

<p>报错了。</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs css">&#123;&quot;<span class="hljs-selector-tag">code</span>&quot;:<span class="hljs-number">500</span>,<span class="hljs-string">&quot;message&quot;</span>:<span class="hljs-string">&quot;Unknown column &#x27;p.recommend_status&#x27; in &#x27;where clause&#x27;&quot;</span>&#125;<br></code></pre></td></tr></table></figure>

<p>数据库字段：recommend 拼写错误。</p>
<p>商品的审核状态，后台提供详情列表页面，审核，未审核不予上架。</p>
<p>后台，查看。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;el-table-column label=&quot;操作&quot; width=&quot;160&quot; align=&quot;center&quot;&gt;<br>          &lt;template slot-scope=&quot;scope&quot;&gt;<br>            &lt;p&gt;<br>              &lt;el-button<br>                size=&quot;mini&quot;<br>                @click=&quot;handleShowProduct(scope.$index, scope.row)&quot;<br>                &gt;查看<br>              &lt;/el-button&gt;<br>              &lt;el-button<br>                size=&quot;mini&quot;<br>                @click=&quot;handleUpdateProduct(scope.$index, scope.row)&quot;<br>                &gt;编辑<br>              &lt;/el-button&gt;<br>            &lt;/p&gt;<br>            &lt;p&gt;<br>              &lt;el-button<br>                size=&quot;mini&quot;<br>                @click=&quot;handleShowLog(scope.$index, scope.row)&quot;<br>                &gt;日志<br>              &lt;/el-button&gt;<br>              &lt;el-button<br>                size=&quot;mini&quot;<br>                type=&quot;danger&quot;<br>                @click=&quot;handleDelete(scope.$index, scope.row)&quot;<br>                &gt;删除<br>              &lt;/el-button&gt;<br>            &lt;/p&gt;<br>          &lt;/template&gt;<br>        &lt;/el-table-column&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-title function_">handleShowProduct</span>(<span class="hljs-params">index, row</span>) &#123;<br>     <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;handleShowProduct&quot;</span>, row);<br>     <span class="hljs-variable language_">this</span>.$message(&#123;<br>       <span class="hljs-attr">message</span>: <span class="hljs-string">`$row`</span>,<br>       <span class="hljs-attr">type</span>: <span class="hljs-string">&quot;warning&quot;</span>,<br>       <span class="hljs-attr">duration</span>: <span class="hljs-number">1000</span><br>     &#125;);<br>   &#125;,<br></code></pre></td></tr></table></figure>

<figure class="highlight arcade"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs arcade"><span class="hljs-string">`商品ID: <span class="hljs-subst">$&#123;row.id&#125;</span> 名称: <span class="hljs-subst">$&#123;row.name&#125;</span>`</span><br></code></pre></td></tr></table></figure>

<p>订单管理。退货管理。购物车管理，通知管理。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 商品信息</span><br><span class="hljs-comment">-- auto-generated definition</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> pms_product<br>(<br>    name                          <span class="hljs-type">varchar</span>(<span class="hljs-number">200</span>)   <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品名称&#x27;</span>,<br>    brand_name                    <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;品牌名称&#x27;</span>,<br>    product_category_id           <span class="hljs-type">bigint</span>         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品分类&#x27;</span>,<br>    pic                           <span class="hljs-type">varchar</span>(<span class="hljs-number">2550</span>)  <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品样图&#x27;</span>,<br>    delete_status                 <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;删除状态(0 - 未删除；1 - 已删除)&#x27;</span>,<br>    publish_status                <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;上架状态(0 - 下架；1 - 上架)&#x27;</span>,<br>    new_status                    <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;新品状态(0 - 不是新品；1 - 新品)&#x27;</span>,<br>    recommend_status              <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;推荐状态(0 - 不推荐；1 - 推荐)&#x27;</span>,<br>    verify_status                 <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;审核状态：0-&gt;未审核；1-&gt;审核通过&#x27;</span>,<br>    sale                          <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;销量&#x27;</span>,<br>    price                         <span class="hljs-type">decimal</span>(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;销售价格&#x27;</span>,<br>    sub_title                     <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>)   <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;副标题&#x27;</span>,<br>    description                   text           <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;商品描述&#x27;</span>,<br>    stock                         <span class="hljs-type">int</span>            <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;库存&#x27;</span>,<br>    promotion_type                <span class="hljs-type">int</span>(<span class="hljs-number">1</span>)         <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;促销类型：0-&gt;没有促销使用原价;1-&gt;使用促销价；2-&gt;使用会员价；3-&gt;使用阶梯价格；4-&gt;使用满减价格；5-&gt;限时购&#x27;</span>,<br>)<br>    comment <span class="hljs-string">&#x27;商品信息&#x27;</span> charset <span class="hljs-operator">=</span> utf8<br>                       row_format <span class="hljs-operator">=</span> <span class="hljs-keyword">DYNAMIC</span>;<br></code></pre></td></tr></table></figure>

<p>商品信息详情。</p>
<p>明天做个查看页面，完善商品管理，订单管理，促销活动。</p>
<blockquote>
<p>2025 年 4 月 27 日</p>
</blockquote>
<p>受不了。</p>
<p>弹框中包含描述列表，这 ElementUI 怎么咋就这么不靠谱，半天调试不出来，不会在前端组件上再多浪费一点时间了。</p>
<p>添加购物车。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">let</span> cartItem = &#123;<br>  <span class="hljs-attr">price</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">product</span>.<span class="hljs-property">price</span>,<br>  <span class="hljs-attr">productAttr</span>: productSkuStock.<span class="hljs-property">spData</span>,<br>  <span class="hljs-attr">productBrand</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">product</span>.<span class="hljs-property">brandName</span>,<br>  <span class="hljs-attr">productCategoryId</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">product</span>.<span class="hljs-property">productCategoryId</span>,<br>  <span class="hljs-attr">productId</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">product</span>.<span class="hljs-property">id</span>,<br>  <span class="hljs-attr">productName</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">product</span>.<span class="hljs-property">name</span>,<br>  <span class="hljs-attr">productPic</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">product</span>.<span class="hljs-property">pic</span>,<br>  <span class="hljs-attr">productSkuCode</span>: productSkuStock.<span class="hljs-property">skuCode</span>,<br>  <span class="hljs-attr">productSkuId</span>: productSkuStock.<span class="hljs-property">id</span>,<br>  <span class="hljs-attr">productSn</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">product</span>.<span class="hljs-property">productSn</span>,<br>  <span class="hljs-attr">productSubTitle</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">product</span>.<span class="hljs-property">subTitle</span>,<br>  <span class="hljs-attr">quantity</span>: <span class="hljs-number">1</span>,<br>&#125;;<br></code></pre></td></tr></table></figure>

<p>这代码有什么毛病。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash">chunk-vendors.js:19078  [system] TypeError: Cannot <span class="hljs-built_in">read</span> properties of null (reading <span class="hljs-string">&#x27;spData&#x27;</span>)<br>    at VueComponent.addToCart (VM1025 nMKJ:751:38)<br>    at click (pages-product-product.js:759:37)<br>    at invokeWithErrorHandling (chunk-vendors.js:21356:26)<br>    at invoker (chunk-vendors.js:21681:14)<br>    at invokeWithErrorHandling (chunk-vendors.js:21356:26)<br>    at HTMLElement.invoker (chunk-vendors.js:21677:9)<br>    at original._wrapper (chunk-vendors.js:26565:25)<br></code></pre></td></tr></table></figure>

<p>控制台偷偷报错这么久。</p>
<p>添加购物车成功了，接下来搞下单，订单展示商品有问题。</p>
<p>推荐品牌列表。</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span> <span class="hljs-attr">&quot;code&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">500</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;message&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;Unknown column &#x27;s.sort&#x27; in &#x27;order clause&#x27;&quot;</span> <span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;select<br>  id=&quot;getRecommendSubjectList&quot;<br>  resultMap=&quot;com.macro.mall.mapper.CmsSubjectMapper.BaseResultMap&quot;<br>&gt;<br>        SELECT s.*<br>        FROM<br>            cms_subject s<br>        WHERE<br>            s.recommend_status = 1<br>            AND s.show_status = 1<br>        LIMIT #&#123;offset&#125;, #&#123;limit&#125;;<br>    &lt;/select&gt;<br></code></pre></td></tr></table></figure>

<p>造了点数据，关联库存表，库存表是关键。</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">this</span>.memberReceiveAddressList = response.<span class="hljs-keyword">data</span>.memberReceiveAddressList;<br>			console.log(<span class="hljs-keyword">this</span>.memberReceiveAddressList)<br>			<span class="hljs-keyword">this</span>.currentAddress = <span class="hljs-keyword">this</span>.getDefaultAddress();<br>			console.log(<span class="hljs-string">&quot;----&quot;</span> + <span class="hljs-keyword">this</span>.currentAddress.city);<br>			<span class="hljs-keyword">this</span>.cartPromotionItemList = response.<span class="hljs-keyword">data</span>.cartPromotionItemList;<br>			console.log(<span class="hljs-keyword">this</span>.cartPromotionItemList)<br></code></pre></td></tr></table></figure>

<p>这都能打印出来了，为什么显示不来列表。。</p>
<p>响应式更新。</p>
<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs kotlin"><span class="hljs-keyword">try</span> &#123;<br>  <span class="hljs-keyword">const</span> response = await generateConfirmOrder(JSON.stringify(<span class="hljs-keyword">this</span>.cartIds));<br>  <span class="hljs-keyword">const</span> res = response.<span class="hljs-keyword">data</span>;<br><br>  <span class="hljs-comment">// 使用 Vue.set 或展开运算符确保响应式更新</span><br>  <span class="hljs-keyword">this</span>.cartPromotionItemList = [...res.cartPromotionItemList]; <span class="hljs-comment">// 深拷贝数组</span><br>  <span class="hljs-keyword">this</span>.currentAddress = &#123; ...<span class="hljs-keyword">this</span>.getDefaultAddress() &#125;; <span class="hljs-comment">// 确保地址是响应式</span><br><br>  console.log(<span class="hljs-string">&quot;购物车数据:&quot;</span>, <span class="hljs-keyword">this</span>.cartPromotionItemList); <span class="hljs-comment">// 确认数据格式</span><br>&#125; <span class="hljs-keyword">catch</span> (err) &#123;<br>  console.error(<span class="hljs-string">&quot;加载数据失败:&quot;</span>, err);<br>  uni.showToast(&#123; title: <span class="hljs-string">&quot;加载失败&quot;</span>, icon: <span class="hljs-string">&quot;none&quot;</span> &#125;);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>方法 1：强制响应式更新（推荐）</strong></p>
<p>javascript</p>
<p>复制</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">async</span> <span class="hljs-title function_">loadData</span>(<span class="hljs-params"></span>) &#123;<br>  <span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> <span class="hljs-title function_">generateConfirmOrder</span>(<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">cartIds</span>));<br>    <span class="hljs-keyword">const</span> res = response.<span class="hljs-property">data</span>;<br><br>    <span class="hljs-comment">// 使用 Vue.set 或展开运算符确保响应式更新</span><br>    <span class="hljs-variable language_">this</span>.<span class="hljs-property">cartPromotionItemList</span> = [...res.<span class="hljs-property">cartPromotionItemList</span>]; <span class="hljs-comment">// 深拷贝数组</span><br>    <span class="hljs-variable language_">this</span>.<span class="hljs-property">currentAddress</span> = &#123; ...<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">getDefaultAddress</span>() &#125;; <span class="hljs-comment">// 确保地址是响应式</span><br><br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;购物车数据:&quot;</span>, <span class="hljs-variable language_">this</span>.<span class="hljs-property">cartPromotionItemList</span>); <span class="hljs-comment">// 确认数据格式</span><br>  &#125; <span class="hljs-keyword">catch</span> (err) &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&quot;加载数据失败:&quot;</span>, err);<br>    uni.<span class="hljs-title function_">showToast</span>(&#123; <span class="hljs-attr">title</span>: <span class="hljs-string">&quot;加载失败&quot;</span>, <span class="hljs-attr">icon</span>: <span class="hljs-string">&quot;none&quot;</span> &#125;);<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><strong>方法 2：确保模板渲染时机</strong></p>
<p>在模板中添加 <code>v-if</code>，避免数据未加载时渲染：</p>
<p>html</p>
<p>运行</p>
<p>复制</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">&quot;cartPromotionItemList.length &gt; 0&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;g-item&quot;</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">&quot;item in cartPromotionItemList&quot;</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">&quot;item.id&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 商品内容 --&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">v-else</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">text</span>&gt;</span>加载中或购物车为空...<span class="hljs-tag">&lt;/<span class="hljs-name">text</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs js">uni.$emit(<span class="hljs-string">&quot;updateData&quot;</span>, &#123; <span class="hljs-attr">list</span>: res.<span class="hljs-property">cartPromotionItemList</span> &#125;);<br></code></pre></td></tr></table></figure>

<p>根本没道理，又是无聊的前端。。。</p>
<p>妈的。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">//创建订单</span><br>		<span class="hljs-title function_">createOrder</span>(<span class="hljs-params"></span>) &#123;<br>			<span class="hljs-keyword">let</span> list = <span class="hljs-variable language_">this</span>.<span class="hljs-property">cartList</span>;<br>			<span class="hljs-keyword">let</span> cartIds = [];<br>			list.<span class="hljs-title function_">forEach</span>(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> &#123;<br>				<span class="hljs-keyword">if</span> (item.<span class="hljs-property">checked</span>) &#123;<br>					cartIds.<span class="hljs-title function_">push</span>(item.<span class="hljs-property">id</span>);<br>				&#125;<br>			&#125;)<br>			<span class="hljs-keyword">if</span>(cartIds.<span class="hljs-property">length</span>==<span class="hljs-number">0</span>)&#123;<br>				uni.<span class="hljs-title function_">showToast</span>(&#123;<br>					<span class="hljs-attr">title</span>:<span class="hljs-string">&#x27;您还未选择要下单的商品！&#x27;</span>,<br>					<span class="hljs-attr">duration</span>:<span class="hljs-number">1000</span><br>				&#125;)<br>				<span class="hljs-keyword">return</span>;<br>			&#125;<br>			uni.<span class="hljs-title function_">navigateTo</span>(&#123;<br>				<span class="hljs-attr">url</span>: <span class="hljs-string">`/pages/order/createOrder?cartIds=<span class="hljs-subst">$&#123;<span class="hljs-built_in">JSON</span>.stringify(cartIds)&#125;</span>`</span><br>			&#125;)<br>		&#125;<br></code></pre></td></tr></table></figure>

<p>成功了。</p>
<p><img src="http://blog.memory-life.xyz/image-20250427193019459.png" alt="image-20250427193019459"></p>
<p>详情记录在 Uniapp 章节下。</p>
<p><img src="http://blog.memory-life.xyz/image-20250427193759934.png" alt="image-20250427193759934"></p>
<p>创建订单。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@ApiOperation(&quot;根据购物车信息生成订单&quot;)</span><br>  <span class="hljs-meta">@RequestMapping(value = &quot;/generateOrder&quot;, method = RequestMethod.POST)</span><br>  <span class="hljs-meta">@ResponseBody</span><br>  <span class="hljs-keyword">public</span> CommonResult <span class="hljs-title function_">generateOrder</span><span class="hljs-params">(<span class="hljs-meta">@RequestBody</span> OrderParam orderParam)</span> &#123;<br>      Map&lt;String, Object&gt; result = portalOrderService.generateOrder(orderParam);<br>      <span class="hljs-keyword">return</span> CommonResult.success(result, <span class="hljs-string">&quot;下单成功&quot;</span>);<br>  &#125;<br></code></pre></td></tr></table></figure>

<p>调试半天，Debug 模式没打开。。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//发送延迟消息取消订单</span><br>sendDelayMessageCancelOrder(order.getId());<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">sendDelayMessageCancelOrder</span><span class="hljs-params">(Long orderId)</span> &#123;<br>    <span class="hljs-comment">//获取订单超时时间</span><br>    <span class="hljs-type">OmsOrderSetting</span> <span class="hljs-variable">orderSetting</span> <span class="hljs-operator">=</span> orderSettingMapper.selectByPrimaryKey(<span class="hljs-number">1L</span>);<br>    <span class="hljs-type">long</span> <span class="hljs-variable">delayTimes</span> <span class="hljs-operator">=</span> orderSetting.getNormalOrderOvertime() * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>;<br>    <span class="hljs-comment">//发送延迟消息</span><br>    cancelOrderSender.sendMessage(orderId, delayTimes);<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Autowired</span><br><span class="hljs-keyword">private</span> AmqpTemplate amqpTemplate;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">sendMessage</span><span class="hljs-params">(Long orderId,<span class="hljs-keyword">final</span> <span class="hljs-type">long</span> delayTimes)</span>&#123;<br>    <span class="hljs-comment">//给延迟队列发送消息</span><br>    amqpTemplate.convertAndSend(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getExchange(), QueueEnum.QUEUE_TTL_ORDER_CANCEL.getRouteKey(), orderId, <span class="hljs-keyword">new</span> <span class="hljs-title class_">MessagePostProcessor</span>() &#123;<br>        <span class="hljs-meta">@Override</span><br>        <span class="hljs-keyword">public</span> Message <span class="hljs-title function_">postProcessMessage</span><span class="hljs-params">(Message message)</span> <span class="hljs-keyword">throws</span> AmqpException &#123;<br>            <span class="hljs-comment">//给消息设置延迟毫秒值</span><br>            message.getMessageProperties().setExpiration(String.valueOf(delayTimes));<br>            <span class="hljs-keyword">return</span> message;<br>        &#125;<br>    &#125;);<br>    LOGGER.info(<span class="hljs-string">&quot;send orderId:&#123;&#125;&quot;</span>,orderId);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>消息队列。</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs awk"><span class="hljs-regexp">//</span>发送延迟消息取消订单<br><span class="hljs-regexp">//</span> sendDelayMessageCancelOrder(order.getId());<br></code></pre></td></tr></table></figure>

<p>消息队列主要用来处理超时订单的，订单放在队列中，支付超时取消订单。</p>
<p><img src="http://blog.memory-life.xyz/image-20250427211340398.png" alt="image-20250427211340398"></p>
<p>扣库存。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 根据商品的skuId扣减真实库存</span><br><span class="hljs-comment"> */</span><br><span class="hljs-type">int</span> <span class="hljs-title function_">reduceSkuStock</span><span class="hljs-params">(<span class="hljs-meta">@Param(&quot;productSkuId&quot;)</span>Long productSkuId,<span class="hljs-meta">@Param(&quot;quantity&quot;)</span> Integer quantity)</span>;<br><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java">&lt;update id=<span class="hljs-string">&quot;reduceSkuStock&quot;</span>&gt;<br>        UPDATE pms_sku_stock<br>        <span class="hljs-type">SET</span> <span class="hljs-variable">lock_stock</span> <span class="hljs-operator">=</span> lock_stock - #&#123;quantity&#125;,<br>            stock = stock - #&#123;quantity&#125;<br>        <span class="hljs-type">WHERE</span><br>            <span class="hljs-variable">id</span> <span class="hljs-operator">=</span> #&#123;productSkuId&#125;<br>          AND stock - #&#123;quantity&#125; &amp;gt;= <span class="hljs-number">0</span><br>          AND lock_stock - #&#123;quantity&#125; &amp;gt;= <span class="hljs-number">0</span><br>    &lt;/update&gt;<br></code></pre></td></tr></table></figure>

<p>很好，现在最主要的目标，是搞定支付沙箱，又是一个挑战。</p>
<p>后续也要跟进消息队列的实践以及实现原理学习，明天的主要目标：PPT + 支付沙箱，从业务、技术方面流利讲明白这个系统。</p>
<p>重点是订单和支付。</p>
<p>今晚尝试完善其余所有基本功能，着重优化促销活动、优惠券发放以及使用。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;view class=&quot;order-item&quot; hover-class=&quot;common-hover&quot; :hover-stay-time=&quot;50&quot;&gt;<br>					&lt;text class=&quot;yticon icon-shouhoutuikuan&quot;&gt;&lt;/text&gt;<br>					&lt;text&gt;退款/售后&lt;/text&gt;<br>				&lt;/view&gt;<br></code></pre></td></tr></table></figure>

<p>这前台商城，不太稳定。</p>
<p>优惠券还未测试，我的页面基本没有开发，那家伙犯懒了，拉了坨烂代码。</p>
<blockquote>
<p>2025 年 4 月 28 日</p>
</blockquote>
<p>早上开始优化完善，前端页面总有问题，不过核心功能即订单创建交付的流程没有受到影响。</p>
<p>促销活动，秒杀活动还是要搞的，支付模块尽可能学习下。</p>
<p>后台模块操作了下，支持功能还挺丰富，结合 PPT 答辩模板，内容基本可以做到充实，今天下午就开始搞 PPT。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-attr">methods</span>: &#123;<br>		<span class="hljs-comment">/**</span><br><span class="hljs-comment">		 * 加载数据</span><br><span class="hljs-comment">		 */</span><br>		<span class="hljs-keyword">async</span> <span class="hljs-title function_">loadData</span>(<span class="hljs-params"></span>) &#123;<br>			<span class="hljs-title function_">fetchContent</span>().<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> &#123;<br>				<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;onLoad&quot;</span>, response.<span class="hljs-property">data</span>);<br>				<span class="hljs-variable language_">this</span>.<span class="hljs-property">advertiseList</span> = response.<span class="hljs-property">data</span>.<span class="hljs-property">advertiseList</span>;<br>				<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">advertiseList</span>);<br>				<span class="hljs-variable language_">this</span>.<span class="hljs-property">swiperLength</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-property">advertiseList</span>.<span class="hljs-property">length</span>;<br><br>				<span class="hljs-variable language_">this</span>.<span class="hljs-property">titleNViewBackground</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-property">titleNViewBackgroundList</span>[<span class="hljs-number">0</span>];<br>				<span class="hljs-variable language_">this</span>.<span class="hljs-property">brandList</span> = response.<span class="hljs-property">data</span>.<span class="hljs-property">brandList</span>;<br>				<span class="hljs-variable language_">this</span>.<span class="hljs-property">homeFlashPromotion</span> = response.<span class="hljs-property">data</span>.<span class="hljs-property">homeFlashPromotion</span>;<br>				<span class="hljs-variable language_">this</span>.<span class="hljs-property">newProductList</span> = response.<span class="hljs-property">data</span>.<span class="hljs-property">newProductList</span>;<br>				<span class="hljs-variable language_">this</span>.<span class="hljs-property">hotProductList</span> = response.<span class="hljs-property">data</span>.<span class="hljs-property">hotProductList</span>;<br>				<span class="hljs-title function_">fetchRecommendProductList</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">recommendParams</span>).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> &#123;<br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">recommendProductList</span> = response.<span class="hljs-property">data</span>;<br>					uni.<span class="hljs-title function_">stopPullDownRefresh</span>();<br>				&#125;)<br>			&#125;);<br>		&#125;,<br></code></pre></td></tr></table></figure>

<p>获取首页内容。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br>   <span class="hljs-keyword">public</span> HomeContentResult <span class="hljs-title function_">content</span><span class="hljs-params">()</span> &#123;<br>       <span class="hljs-type">HomeContentResult</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HomeContentResult</span>();<br>       <span class="hljs-comment">//获取首页广告</span><br>       result.setAdvertiseList(getHomeAdvertiseList());<br>       <span class="hljs-comment">//获取推荐品牌</span><br>       result.setBrandList(homeDao.getRecommendBrandList(<span class="hljs-number">0</span>,<span class="hljs-number">6</span>));<br>       <span class="hljs-comment">//获取秒杀信息</span><br>       result.setHomeFlashPromotion(getHomeFlashPromotion());<br>       <span class="hljs-comment">//获取新品推荐</span><br>       result.setNewProductList(homeDao.getNewProductList(<span class="hljs-number">0</span>,<span class="hljs-number">4</span>));<br>       <span class="hljs-comment">//获取人气推荐</span><br>       result.setHotProductList(homeDao.getHotProductList(<span class="hljs-number">0</span>,<span class="hljs-number">4</span>));<br>       <span class="hljs-comment">//获取推荐专题</span><br>       result.setSubjectList(homeDao.getRecommendSubjectList(<span class="hljs-number">0</span>,<span class="hljs-number">4</span>));<br>       <span class="hljs-keyword">return</span> result;<br>   &#125;<br></code></pre></td></tr></table></figure>

<p>获取促销活动列表。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">private</span> HomeFlashPromotion <span class="hljs-title function_">getHomeFlashPromotion</span><span class="hljs-params">()</span> &#123;<br>       <span class="hljs-type">HomeFlashPromotion</span> <span class="hljs-variable">homeFlashPromotion</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HomeFlashPromotion</span>();<br>       <span class="hljs-comment">//获取当前秒杀活动</span><br>       <span class="hljs-type">Date</span> <span class="hljs-variable">now</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>();<br>       <span class="hljs-type">SmsFlashPromotion</span> <span class="hljs-variable">flashPromotion</span> <span class="hljs-operator">=</span> getFlashPromotion(now);<br>       <span class="hljs-keyword">if</span> (flashPromotion != <span class="hljs-literal">null</span>) &#123;<br>           <span class="hljs-comment">//获取当前秒杀场次</span><br>           <span class="hljs-type">SmsFlashPromotionSession</span> <span class="hljs-variable">flashPromotionSession</span> <span class="hljs-operator">=</span> getFlashPromotionSession(now);<br>           <span class="hljs-keyword">if</span> (flashPromotionSession != <span class="hljs-literal">null</span>) &#123;<br>               homeFlashPromotion.setStartTime(flashPromotionSession.getStartTime());<br>               homeFlashPromotion.setEndTime(flashPromotionSession.getEndTime());<br>               <span class="hljs-comment">//获取下一个秒杀场次</span><br>               <span class="hljs-type">SmsFlashPromotionSession</span> <span class="hljs-variable">nextSession</span> <span class="hljs-operator">=</span> getNextFlashPromotionSession(homeFlashPromotion.getStartTime());<br>               <span class="hljs-keyword">if</span>(nextSession!=<span class="hljs-literal">null</span>)&#123;<br>                   homeFlashPromotion.setNextStartTime(nextSession.getStartTime());<br>                   homeFlashPromotion.setNextEndTime(nextSession.getEndTime());<br>               &#125;<br>               <span class="hljs-comment">//获取秒杀商品</span><br>               List&lt;FlashPromotionProduct&gt; flashProductList = homeDao.getFlashProductList(flashPromotion.getId(), flashPromotionSession.getId());<br>               homeFlashPromotion.setProductList(flashProductList);<br>           &#125;<br>       &#125;<br>       <span class="hljs-keyword">return</span> homeFlashPromotion;<br>   &#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs JAVA"><span class="hljs-comment">/**</span><br><span class="hljs-comment">   * 从Date类型的时间中提取时间部分</span><br><span class="hljs-comment">   */</span><br>  <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Date <span class="hljs-title function_">getTime</span><span class="hljs-params">(Date date)</span> &#123;<br>      <span class="hljs-type">Calendar</span> <span class="hljs-variable">calendar</span> <span class="hljs-operator">=</span> Calendar.getInstance();<br>      calendar.setTime(date);<br>      calendar.set(Calendar.YEAR, date.getYear());<br>      calendar.set(Calendar.MONTH, date.getMonth());<br>      calendar.set(Calendar.DAY_OF_MONTH, date.getDay());<br>      <span class="hljs-keyword">return</span> calendar.getTime();<br>  &#125;<br></code></pre></td></tr></table></figure>

<p>直接造数据。</p>
<p>查询秒杀场次犯癫了，自己返回一个固定日期。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;selectByExample&quot;</span> <span class="hljs-attr">parameterType</span>=<span class="hljs-string">&quot;com.macro.mall.model.SmsFlashPromotionSessionExample&quot;</span> <span class="hljs-attr">resultMap</span>=<span class="hljs-string">&quot;BaseResultMap&quot;</span>&gt;</span><br>    select<br>    <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;distinct&quot;</span>&gt;</span><br>      distinct<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">include</span> <span class="hljs-attr">refid</span>=<span class="hljs-string">&quot;Base_Column_List&quot;</span> /&gt;</span><br>    from sms_flash_promotion_session<br>    <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;_parameter != null&quot;</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">include</span> <span class="hljs-attr">refid</span>=<span class="hljs-string">&quot;Example_Where_Clause&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">if</span> <span class="hljs-attr">test</span>=<span class="hljs-string">&quot;orderByClause != null&quot;</span>&gt;</span><br>      order by $&#123;orderByClause&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">if</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@ApiModelProperty(value = &quot;每日开始时间&quot;)</span><br><span class="hljs-keyword">private</span> Date startTime;<br><br><span class="hljs-meta">@ApiModelProperty(value = &quot;每日结束时间&quot;)</span><br><span class="hljs-keyword">private</span> Date endTime;<br><br><br><span class="hljs-type">SmsFlashPromotionSession</span> <span class="hljs-variable">smsFlashPromotionSession</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SmsFlashPromotionSession</span>();<br>    smsFlashPromotionSession.setId(<span class="hljs-number">001L</span>);<br>    smsFlashPromotionSession.setName(<span class="hljs-string">&quot;上午场次&quot;</span>);<br>    smsFlashPromotionSession.setStartTime();<br>    smsFlashPromotionSession.setEndTime();<br>    smsFlashPromotionSession.setStatus(<span class="hljs-number">1</span>);<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-type">SmsFlashPromotionSession</span> <span class="hljs-variable">smsFlashPromotionSession</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SmsFlashPromotionSession</span>();<br>  smsFlashPromotionSession.setId(<span class="hljs-number">001L</span>);<br>  smsFlashPromotionSession.setName(<span class="hljs-string">&quot;上午场次&quot;</span>);<br>  smsFlashPromotionSession.setStartTime(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>(<span class="hljs-string">&quot;08:00:00&quot;</span>)); <span class="hljs-comment">// 图片中的 startTime</span><br>  smsFlashPromotionSession.setEndTime(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>(<span class="hljs-string">&quot;13:00:00&quot;</span>));   <span class="hljs-comment">// 图片中的 endTime</span><br>  smsFlashPromotionSession.setStatus(<span class="hljs-number">1</span>);<br><br>  <span class="hljs-keyword">return</span> smsFlashPromotionSession;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>2025 年 4 月 30 日</p>
</blockquote>
<p>今早结束了预答辩，效果不错，节奏也很不错。</p>
<p>需要完善的两个功能：后端首页数据统计分析图，前台退款售后功能，我的足迹，我的收藏。</p>
<blockquote>
<p>2025 年 5 月 3 日</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@ApiOperation(&quot;分页获取浏览记录&quot;)</span><br><span class="hljs-meta">@RequestMapping(value = &quot;/list&quot;, method = RequestMethod.GET)</span><br><span class="hljs-meta">@ResponseBody</span><br><span class="hljs-keyword">public</span> CommonResult&lt;CommonPage&lt;MemberReadHistory&gt;&gt; <span class="hljs-title function_">list</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(value = &quot;pageNum&quot;, defaultValue = &quot;1&quot;)</span> Integer pageNum,</span><br><span class="hljs-params">                                                        <span class="hljs-meta">@RequestParam(value = &quot;pageSize&quot;, defaultValue = &quot;5&quot;)</span> Integer pageSize)</span> &#123;<br>    Page&lt;MemberReadHistory&gt; page = memberReadHistoryService.list(pageNum, pageSize);<br>    <span class="hljs-keyword">return</span> CommonResult.success(CommonPage.restPage(page));<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br><span class="hljs-keyword">public</span> Page&lt;MemberReadHistory&gt; <span class="hljs-title function_">list</span><span class="hljs-params">(Integer pageNum, Integer pageSize)</span> &#123;<br>    <span class="hljs-type">UmsMember</span> <span class="hljs-variable">member</span> <span class="hljs-operator">=</span> memberService.getCurrentMember();<br>    <span class="hljs-type">Pageable</span> <span class="hljs-variable">pageable</span> <span class="hljs-operator">=</span> PageRequest.of(pageNum - <span class="hljs-number">1</span>, pageSize);<br>    <span class="hljs-keyword">return</span> memberReadHistoryRepository.findByMemberIdOrderByCreateTimeDesc(member.getId(), pageable);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>返回推荐商品列表。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Override</span><br>  <span class="hljs-keyword">public</span> Page&lt;MemberReadHistory&gt; <span class="hljs-title function_">list</span><span class="hljs-params">(Integer pageNum, Integer pageSize)</span> &#123;<br>      List&lt;PmsProduct&gt; productList = homeService.recommendProductList(pageSize, pageNum);<br>      List&lt;MemberReadHistory&gt; readHistoryList = productList.stream().map(product -&gt; &#123;<br>          <span class="hljs-type">MemberReadHistory</span> <span class="hljs-variable">memberReadHistory</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">MemberReadHistory</span>();<br>          memberReadHistory.setProductId(product.getId());<br>          memberReadHistory.setProductName(product.getName());<br>          memberReadHistory.setProductSubTitle(product.getSubTitle());<br>          memberReadHistory.setProductPrice(product.getPrice() + <span class="hljs-string">&quot;&quot;</span>);<br>          memberReadHistory.setProductPic(product.getPic());<br>          <span class="hljs-keyword">return</span> memberReadHistory;<br>      &#125;).collect(Collectors.toList());<br><br>      <span class="hljs-type">Pageable</span> <span class="hljs-variable">pageable</span> <span class="hljs-operator">=</span> PageRequest.of(pageNum, pageSize);<br>      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">PageImpl</span>&lt;&gt;(readHistoryList, pageable, readHistoryList.size());<br>  &#125;<br></code></pre></td></tr></table></figure>

<p>我的收藏，我的关注，最近浏览，全部完成。</p>
<p>登陆有些问题。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"> <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">login</span><span class="hljs-params">(String username, String password)</span> &#123;<br>        <span class="hljs-type">String</span> <span class="hljs-variable">token</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>        <span class="hljs-comment">//密码需要客户端加密后传递</span><br>        <span class="hljs-keyword">try</span> &#123;<br>            <span class="hljs-type">UserDetails</span> <span class="hljs-variable">userDetails</span> <span class="hljs-operator">=</span> loadUserByUsername(username);<br>            <span class="hljs-keyword">if</span>(!passwordEncoder.matches(password,userDetails.getPassword()))&#123;<br>                Asserts.fail(<span class="hljs-string">&quot;密码不正确&quot;</span>);<br>            &#125;<br>            <span class="hljs-keyword">if</span>(!userDetails.isEnabled())&#123;<br>                Asserts.fail(<span class="hljs-string">&quot;帐号已被禁用&quot;</span>);<br>            &#125;<br>            <span class="hljs-type">UsernamePasswordAuthenticationToken</span> <span class="hljs-variable">authentication</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernamePasswordAuthenticationToken</span>(userDetails, <span class="hljs-literal">null</span>, userDetails.getAuthorities());<br>            SecurityContextHolder.getContext().setAuthentication(authentication);<br>            token = jwtTokenUtil.generateToken(userDetails);<br><span class="hljs-comment">//            updateLoginTimeByUsername(username);</span><br>            insertLoginLog(username);<br>        &#125; <span class="hljs-keyword">catch</span> (AuthenticationException e) &#123;<br>            LOGGER.warn(<span class="hljs-string">&quot;登录异常:&#123;&#125;&quot;</span>, e.getMessage());<br>        &#125;<br></code></pre></td></tr></table></figure>

<p>用户名错了。。</p>
<p>首页订单量统计，这拉下来的项目接口都没写，直接编造数据吧。</p>
<blockquote>
<p>2025 年 5 月 8 日</p>
</blockquote>
<p>退货申请。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">showModal:</span> <span class="hljs-literal">false</span><span class="hljs-string">,</span><br><span class="hljs-attr">returnReason:</span> <span class="hljs-string">&#x27;&#x27;</span><span class="hljs-string">,</span><br><span class="hljs-attr">currentOrderId:</span> <span class="hljs-literal">null</span><span class="hljs-string">,</span><br></code></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;action-box b-t&quot;</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">&quot;item.status == 3&quot;</span>&gt;</span><br>							<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;action-btn&quot;</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;showReturnDialog(item.id)&quot;</span> &gt;</span>申请退货<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>							<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;action-btn recom&quot;</span> &gt;</span>评价商品<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>						<span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span><br><br>						  <span class="hljs-comment">&lt;!-- 自定义弹窗 --&gt;</span><br>						  <span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;custom-modal&quot;</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">&quot;showModal&quot;</span>&gt;</span><br>						    <span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;modal-content&quot;</span>&gt;</span><br>						      <span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;modal-header&quot;</span>&gt;</span>请输入退货原因<span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span><br>						      <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span></span><br><span class="hljs-tag">						        <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;reason-input&quot;</span></span><br><span class="hljs-tag">						        <span class="hljs-attr">v-model</span>=<span class="hljs-string">&quot;returnReason&quot;</span></span><br><span class="hljs-tag">						        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">&quot;请简要说明退货原因&quot;</span></span><br><span class="hljs-tag">						        <span class="hljs-attr">auto-height</span></span><br><span class="hljs-tag">						      /&gt;</span><br>						      <span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;modal-footer&quot;</span>&gt;</span><br>						        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;btn cancel&quot;</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;closeModal&quot;</span>&gt;</span>取消<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>						        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;btn confirm&quot;</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;submitReturn&quot;</span>&gt;</span>确定<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>						      <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span><br>						    <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span><br>						  <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs kotlin">showReturnDialog(orderId) &#123;<br>		      <span class="hljs-keyword">this</span>.currentOrderId = orderId<br>		      <span class="hljs-keyword">this</span>.showModal = <span class="hljs-literal">true</span><br>		    &#125;,<br>			submitReturn() &#123;<br>			      <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.returnReason.trim()) &#123;<br>			        uni.showToast(&#123; title: <span class="hljs-string">&#x27;请输入退货原因&#x27;</span>, icon: <span class="hljs-string">&#x27;none&#x27;</span> &#125;)<br>			        <span class="hljs-keyword">return</span><br>			      &#125;<br><br>			      uni.showLoading(&#123; title: <span class="hljs-string">&#x27;处理中...&#x27;</span> &#125;)<br>			      cancelUserOrder(&#123;<br>			        orderId: <span class="hljs-keyword">this</span>.currentOrderId,<br>			        reason: <span class="hljs-keyword">this</span>.returnReason<br>			      &#125;).then(response =&gt; &#123;<br>			        uni.hideLoading()<br>			        <span class="hljs-keyword">this</span>.showModal = <span class="hljs-literal">false</span><br>			        <span class="hljs-keyword">this</span>.returnReason = <span class="hljs-string">&#x27;&#x27;</span><br>			        <span class="hljs-keyword">this</span>.loadData()<br>			        uni.showToast(&#123; title: <span class="hljs-string">&#x27;退货申请已提交&#x27;</span> &#125;)<br>			      &#125;)<br>			    &#125;,<br><br>			    closeModal() &#123;<br>			      <span class="hljs-keyword">this</span>.showModal = <span class="hljs-literal">false</span><br>			      <span class="hljs-keyword">this</span>.returnReason = <span class="hljs-string">&#x27;&#x27;</span><br>			    &#125;,<br></code></pre></td></tr></table></figure>

<p>这样的效果有点难看。</p>
<p><img src="http://blog.memory-life.xyz/image-20250508215146638.png" alt="image-20250508215146638"></p>
<p>优化版弹窗。</p>
<figure class="highlight dust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><code class="hljs dust"><span class="language-xml"><span class="hljs-comment">&lt;!-- 优化版弹窗 --&gt;</span></span><br><span class="language-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">view</span></span></span><br><span class="hljs-tag"><span class="language-xml">    <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;custom-modal&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">    <span class="hljs-attr">:class</span>=<span class="hljs-string">&quot;</span></span></span><span class="hljs-template-variable">&#123; &#x27;modal-show&#x27;: showModal &#125;</span><span class="language-xml"><span class="hljs-tag"><span class="hljs-string">&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">    @<span class="hljs-attr">touchmove.prevent</span></span></span><br><span class="hljs-tag"><span class="language-xml">    @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;closeModal&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">  &gt;</span></span><br><span class="language-xml">    <span class="hljs-tag">&lt;<span class="hljs-name">view</span></span></span><br><span class="hljs-tag"><span class="language-xml">      <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;modal-content&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">      @<span class="hljs-attr">click.stop</span></span></span><br><span class="hljs-tag"><span class="language-xml">    &gt;</span></span><br><span class="language-xml">      <span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;modal-header&quot;</span>&gt;</span></span><br><span class="language-xml">        <span class="hljs-tag">&lt;<span class="hljs-name">text</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;title&quot;</span>&gt;</span>退货申请<span class="hljs-tag">&lt;/<span class="hljs-name">text</span>&gt;</span></span><br><span class="language-xml">        <span class="hljs-tag">&lt;<span class="hljs-name">text</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;subtitle&quot;</span>&gt;</span>（请详细说明退货原因）<span class="hljs-tag">&lt;/<span class="hljs-name">text</span>&gt;</span></span><br><span class="language-xml">      <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span></span><br><span class="language-xml">      <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span></span></span><br><span class="hljs-tag"><span class="language-xml">        <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;reason-input&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        <span class="hljs-attr">v-model</span>=<span class="hljs-string">&quot;returnReason&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">&quot;请输入至少10个字的退货说明...&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        <span class="hljs-attr">placeholder-class</span>=<span class="hljs-string">&quot;placeholder-style&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        <span class="hljs-attr">:maxlength</span>=<span class="hljs-string">&quot;200&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        <span class="hljs-attr">:auto-height</span>=<span class="hljs-string">&quot;true&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        <span class="hljs-attr">:show-confirm-bar</span>=<span class="hljs-string">&quot;false&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        <span class="hljs-attr">:focus</span>=<span class="hljs-string">&quot;showModal&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        @<span class="hljs-attr">input</span>=<span class="hljs-string">&quot;onInput&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">      /&gt;</span></span><br><span class="language-xml">      <span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;word-counter&quot;</span>&gt;</span></span><span class="hljs-template-variable">&#123;&#123; returnReason.length &#125;</span><span class="language-xml">&#125;/200<span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span></span><br><span class="language-xml">      <span class="hljs-tag">&lt;<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;modal-footer&quot;</span>&gt;</span></span><br><span class="language-xml">        <span class="hljs-tag">&lt;<span class="hljs-name">button</span></span></span><br><span class="hljs-tag"><span class="language-xml">          <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;btn cancel&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">          <span class="hljs-attr">hover-class</span>=<span class="hljs-string">&quot;btn-hover&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">          @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;closeModal&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        &gt;</span></span><br><span class="language-xml">          取消</span><br><span class="language-xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span><br><span class="language-xml">        <span class="hljs-tag">&lt;<span class="hljs-name">button</span></span></span><br><span class="hljs-tag"><span class="language-xml">          <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;btn confirm&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">          <span class="hljs-attr">:class</span>=<span class="hljs-string">&quot;</span></span></span><span class="hljs-template-variable">&#123; &#x27;disabled&#x27;: !canSubmit &#125;</span><span class="language-xml"><span class="hljs-tag"><span class="hljs-string">&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">          <span class="hljs-attr">hover-class</span>=<span class="hljs-string">&quot;btn-hover&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">          @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;submitReturn&quot;</span></span></span><br><span class="hljs-tag"><span class="language-xml">        &gt;</span></span><br><span class="language-xml">          提交申请</span><br><span class="language-xml">        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span><br><span class="language-xml">      <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span></span><br><span class="language-xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span></span><br><span class="language-xml">  <span class="hljs-tag">&lt;/<span class="hljs-name">view</span>&gt;</span></span><br></code></pre></td></tr></table></figure>

<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-comment">/* 优化后的样式 */</span><br><span class="hljs-selector-class">.custom-modal</span> &#123;<br>  <span class="hljs-attribute">position</span>: fixed;<br>  <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;<br>  <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;<br>  <span class="hljs-attribute">right</span>: <span class="hljs-number">0</span>;<br>  <span class="hljs-attribute">bottom</span>: <span class="hljs-number">0</span>;<br>  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.5</span>);<br>  <span class="hljs-attribute">display</span>: flex;<br>  <span class="hljs-attribute">justify-content</span>: center;<br>  <span class="hljs-attribute">align-items</span>: center;<br>  <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0</span>;<br>  <span class="hljs-attribute">visibility</span>: hidden;<br>  <span class="hljs-attribute">transition</span>: all <span class="hljs-number">0.3s</span> ease;<br>  <span class="hljs-attribute">z-index</span>: <span class="hljs-number">9999</span>;<br><br>  &amp;<span class="hljs-selector-class">.modal-show</span> &#123;<br>    <span class="hljs-attribute">opacity</span>: <span class="hljs-number">1</span>;<br>    <span class="hljs-attribute">visibility</span>: visible;<br>  &#125;<br>&#125;<br><br><span class="hljs-selector-class">.modal-content</span> &#123;<br>  <span class="hljs-attribute">width</span>: <span class="hljs-number">85%</span>;<br>  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">600</span>rpx;<br>  <span class="hljs-attribute">background</span>: <span class="hljs-number">#fff</span>;<br>  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">16</span>rpx;<br>  <span class="hljs-attribute">padding</span>: <span class="hljs-number">32</span>rpx;<br>  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateY</span>(<span class="hljs-number">50px</span>);<br>  <span class="hljs-attribute">transition</span>: transform <span class="hljs-number">0.3s</span> ease;<br><br>  <span class="hljs-selector-class">.custom-modal</span><span class="hljs-selector-class">.modal-show</span> &amp; &#123;<br>    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateY</span>(<span class="hljs-number">0</span>);<br>  &#125;<br>&#125;<br><br><span class="hljs-selector-class">.modal-header</span> &#123;<br>  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">32</span>rpx;<br><br>  <span class="hljs-selector-class">.title</span> &#123;<br>    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">36</span>rpx;<br>    <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">600</span>;<br>    <span class="hljs-attribute">color</span>: <span class="hljs-number">#303133</span>;<br>  &#125;<br><br>  <span class="hljs-selector-class">.subtitle</span> &#123;<br>    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24</span>rpx;<br>    <span class="hljs-attribute">color</span>: <span class="hljs-number">#909399</span>;<br>    <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">16</span>rpx;<br>  &#125;<br>&#125;<br><br><span class="hljs-selector-class">.reason-input</span> &#123;<br>  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;<br>  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">240</span>rpx;<br>  <span class="hljs-attribute">padding</span>: <span class="hljs-number">24</span>rpx;<br>  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">28</span>rpx;<br>  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>;<br>  <span class="hljs-attribute">border</span>: <span class="hljs-number">2</span>rpx solid <span class="hljs-number">#dcdfe6</span>;<br>  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">8</span>rpx;<br>  <span class="hljs-attribute">background</span>: <span class="hljs-number">#f8f8f8</span>;<br>  <span class="hljs-attribute">transition</span>: border-color <span class="hljs-number">0.3s</span>;<br><br>  &amp;<span class="hljs-selector-pseudo">:focus</span> &#123;<br>    <span class="hljs-attribute">border-color</span>: <span class="hljs-number">#007aff</span>;<br>    <span class="hljs-attribute">background</span>: <span class="hljs-number">#fff</span>;<br>  &#125;<br>&#125;<br><br><span class="hljs-selector-class">.placeholder-style</span> &#123;<br>  <span class="hljs-attribute">color</span>: <span class="hljs-number">#c0c4cc</span>;<br>&#125;<br><br><span class="hljs-selector-class">.word-counter</span> &#123;<br>  <span class="hljs-attribute">text-align</span>: right;<br>  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24</span>rpx;<br>  <span class="hljs-attribute">color</span>: <span class="hljs-number">#909399</span>;<br>  <span class="hljs-attribute">margin</span>: <span class="hljs-number">16</span>rpx <span class="hljs-number">0</span> <span class="hljs-number">32</span>rpx;<br>&#125;<br><br><span class="hljs-selector-class">.modal-footer</span> &#123;<br>  <span class="hljs-attribute">display</span>: flex;<br>  <span class="hljs-attribute">justify-content</span>: space-between;<br>  <span class="hljs-attribute">gap</span>: <span class="hljs-number">32</span>rpx;<br>&#125;<br><br><span class="hljs-selector-class">.btn</span> &#123;<br>  <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span>;<br>  <span class="hljs-attribute">height</span>: <span class="hljs-number">80</span>rpx;<br>  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">80</span>rpx;<br>  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">8</span>rpx;<br>  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">32</span>rpx;<br>  <span class="hljs-attribute">transition</span>: all <span class="hljs-number">0.2s</span>;<br><br>  &amp;<span class="hljs-selector-pseudo">::after</span> &#123;<br>    <span class="hljs-attribute">border</span>: none;<br>  &#125;<br><br>  &amp;<span class="hljs-selector-class">.cancel</span> &#123;<br>    <span class="hljs-attribute">background</span>: <span class="hljs-number">#f0f0f0</span>;<br>    <span class="hljs-attribute">color</span>: <span class="hljs-number">#606266</span>;<br><br>    &amp;<span class="hljs-selector-pseudo">:active</span> &#123;<br>      <span class="hljs-attribute">background</span>: <span class="hljs-number">#e0e0e0</span>;<br>    &#125;<br>  &#125;<br><br>  &amp;<span class="hljs-selector-class">.confirm</span> &#123;<br>    <span class="hljs-attribute">background</span>: <span class="hljs-number">#007aff</span>;<br>    <span class="hljs-attribute">color</span>: white;<br><br>    &amp;<span class="hljs-selector-pseudo">:active</span> &#123;<br>      <span class="hljs-attribute">background</span>: <span class="hljs-number">#0062cc</span>;<br>    &#125;<br><br>    &amp;<span class="hljs-selector-class">.disabled</span> &#123;<br>      <span class="hljs-attribute">background</span>: <span class="hljs-number">#c0c4cc</span>;<br>      <span class="hljs-attribute">cursor</span>: not-allowed;<br>    &#125;<br>  &#125;<br>&#125;<br><br><span class="hljs-selector-class">.btn-hover</span> &#123;<br>  <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0.8</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250508225909510.png" alt="image-20250508225909510"></p>
<p>使用 uni 对话框组件。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install @dcloudio/uni-ui<br></code></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;!-- 退货原因弹窗 --&gt;<br>&lt;uni-popup ref=&quot;returnPopup&quot; type=&quot;dialog&quot;&gt;<br>    &lt;uni-popup-dialog<br>      mode=&quot;input&quot;<br>      title=&quot;请输入退货原因&quot;<br>      :value=&quot;returnReason&quot;<br>      @confirm=&quot;confirmReturn&quot;<br>      @close=&quot;closeReturn&quot;<br>    &gt;&lt;/uni-popup-dialog&gt;<br>  &lt;/uni-popup&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> uniPopup <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@dcloudio/uni-ui/lib/uni-popup/uni-popup.vue&quot;</span>;<br><span class="hljs-keyword">import</span> uniPopupDialog <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@dcloudio/uni-ui/lib/uni-popup-dialog/uni-popup-dialog.vue&quot;</span>;<br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-title function_">showReturnDialog</span>(<span class="hljs-params">orderId</span>) &#123;<br>      <span class="hljs-variable language_">this</span>.<span class="hljs-property">currentOrderId</span> = orderId<br>      <span class="hljs-variable language_">this</span>.<span class="hljs-property">$refs</span>.<span class="hljs-property">returnPopup</span>.<span class="hljs-title function_">open</span>()<br>    &#125;,<br><br>    <span class="hljs-title function_">confirmReturn</span>(<span class="hljs-params">value</span>) &#123;<br>      <span class="hljs-keyword">if</span> (!value) &#123;<br>        uni.<span class="hljs-title function_">showToast</span>(&#123; <span class="hljs-attr">title</span>: <span class="hljs-string">&#x27;请输入退货原因&#x27;</span>, <span class="hljs-attr">icon</span>: <span class="hljs-string">&#x27;none&#x27;</span> &#125;)<br>        <span class="hljs-keyword">return</span><br>      &#125;<br><br>      uni.<span class="hljs-title function_">showLoading</span>(&#123; <span class="hljs-attr">title</span>: <span class="hljs-string">&#x27;处理中...&#x27;</span> &#125;)<br>      <span class="hljs-title function_">cancelUserOrder</span>(&#123;<br>        <span class="hljs-attr">orderId</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">currentOrderId</span>,<br>        <span class="hljs-attr">reason</span>: value<br>      &#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> &#123;<br>        uni.<span class="hljs-title function_">hideLoading</span>()<br>        <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">loadData</span>()<br>        <span class="hljs-variable language_">this</span>.<span class="hljs-property">$refs</span>.<span class="hljs-property">returnPopup</span>.<span class="hljs-title function_">close</span>()<br>        uni.<span class="hljs-title function_">showToast</span>(&#123; <span class="hljs-attr">title</span>: <span class="hljs-string">&#x27;退货申请已提交&#x27;</span> &#125;)<br>      &#125;)<br>    &#125;,<br><br>    <span class="hljs-title function_">closeReturn</span>(<span class="hljs-params"></span>) &#123;<br>      <span class="hljs-variable language_">this</span>.<span class="hljs-property">returnReason</span> = <span class="hljs-string">&#x27;&#x27;</span><br>      <span class="hljs-variable language_">this</span>.<span class="hljs-property">currentOrderId</span> = <span class="hljs-literal">null</span><br>    &#125;<br></code></pre></td></tr></table></figure>

<p>后台首页。搞定。</p>
<h2 id="装订"><a href="#装订" class="headerlink" title="装订"></a>装订</h2><blockquote>
<p>2025 年 5 月 8 日</p>
</blockquote>
<p>这么快就八号了。</p>
<p>新建文件夹。</p>
<blockquote>
<p>2025 年 5 月 13 日</p>
</blockquote>
<p>距离答辩结束已经过去整整三天了，今天周二，需要对毕设论文以及相关文档做个了结。</p>
<p>最后完善一次。</p>
<h1 id="重学计划"><a href="#重学计划" class="headerlink" title="重学计划"></a>重学计划</h1><h2 id="疯狂-Java"><a href="#疯狂-Java" class="headerlink" title="疯狂 Java"></a>疯狂 Java</h2><blockquote>
<p>2025 年 2 月 10 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_53564801/article/details/135667462">在 Linux 上搭建 Java 环境_linux 安装 java-CSDN 博客</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum list | grep jdk<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install java-1.8.0-openjdk-devel.x86_64<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">java -version<br></code></pre></td></tr></table></figure>

<blockquote>
<p>2025 年 3 月 15 日</p>
</blockquote>
<p>Mybatis，AI 接入，MySQL，微服务，消息队列，Dubbo，WebSocket，Vue，小程序。</p>
<p>其实最重要的还是夯实基础，再去到各个公司官网看看相关业务，有助于针对性学习。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_48373085/article/details/128689811?ops_request_misc=%7B%22request_id%22:%222fe795b46849b1f3be2b248a57c4ab44%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=2fe795b46849b1f3be2b248a57c4ab44&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-128689811-null-null.142%5Ev102%5Econtrol&utm_term=Mybatis%E8%AF%A6%E7%BB%86&spm=1018.2226.3001.4187">【超详细】MyBatis 详解-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/MySQL%E5%AE%9E%E6%88%9845%E8%AE%B2">MySQL 实战 45 讲 (lianglianglee.com)</a></p>
<blockquote>
<p>2025 年 4 月 15 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/6977323236186914852#heading-23">(一)玩命死磕 Java 内存模型（JMM）与 Volatile 关键字底层原理引言 本篇文章结合我个人对 Java 内存模型的理解 - 掘金 (juejin.cn)</a></p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">多条线程同时对一个共享资源进行非原子性操作时会诱发线程安全问题<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7238823745828405308#heading-20">四十五图，一万五千字！一文让你走出迷雾玩转 Maven！Maven 是大家的老熟客，几乎每天都会跟他打交道，不过许多人对它似 - 掘金 (juejin.cn)</a></p>
<h2 id="Vue-基础"><a href="#Vue-基础" class="headerlink" title="Vue 基础"></a>Vue 基础</h2><blockquote>
<p>2025 年 9 月 30 日</p>
</blockquote>
<p>菜鸟教程，连续一周的持续学习，尤其 Vue.js 和 Node.js 讲得不错。</p>
<p><a target="_blank" rel="noopener" href="https://www.runoob.com/vue3/vue3-tutorial.html">Vue3 教程 | 菜鸟教程</a></p>
<blockquote>
<p>2024 年 7 月 26 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://cn.vuejs.org/">Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/column/7211439925144502330">Vue.js 基础理论实操 - itsOli 的专栏 - 掘金 (juejin.cn)</a></p>
<blockquote>
<p>2025 年 1 月 16 日</p>
</blockquote>
<p>早上第一件事，学学 Vue。</p>
<blockquote>
<p>2025 年 2 月 11 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/xiaoaque/article/details/144616201">Vue.js 安装_vue.js 下载-CSDN 博客</a></p>
<p>原生 JS：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>前端一万小时-Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;app&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="language-javascript"></span><br><span class="language-javascript">      <span class="hljs-keyword">var</span> dom = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&quot;app&quot;</span>);</span><br><span class="language-javascript">      dom.<span class="hljs-property">innerHTML</span> = <span class="hljs-string">&quot;Hello World&quot;</span>;</span><br><span class="language-javascript">    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>引入 Vue：</p>
<p><a target="_blank" rel="noopener" href="https://worktile.com/kb/p/3653162">vue.js 如何下载教程 • Worktile 社区</a></p>
<p><a target="_blank" rel="noopener" href="https://cn.vuejs.org/guide/quick-start.html#using-vue-from-cdn">快速上手 | Vue.js (vuejs.org)</a></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs js">&lt;script src=<span class="hljs-string">&quot;https://unpkg.com/vue@3/dist/vue.global.js&quot;</span>&gt;&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">&quot;X-UA-Compatible&quot;</span> <span class="hljs-attr">content</span>=<span class="hljs-string">&quot;IE=edge&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;viewport&quot;</span> <span class="hljs-attr">content</span>=<span class="hljs-string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Document<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;app&quot;</span>&gt;</span><br>      &#123;&#123;content&#125;&#125;<br>      <span class="hljs-comment">&lt;!-- 2️⃣-⑥：用 &#123;&#123;&#125;&#125; 包裹 content，写在 #app 这个 div 里。 --&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="language-javascript"></span><br><span class="language-javascript">      <span class="hljs-keyword">var</span> app = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Vue</span>(&#123;</span><br><span class="language-javascript">        <span class="hljs-comment">// 2️⃣-②：创建一个 Vue 实例；</span></span><br><span class="language-javascript"></span><br><span class="language-javascript">        <span class="hljs-attr">el</span>: <span class="hljs-string">&quot;#app&quot;</span>, <span class="hljs-comment">// 2️⃣-③：这个实例接收的第一个参数 el，稍后会详细讲解它，暂时不管；</span></span><br><span class="language-javascript"></span><br><span class="language-javascript">        <span class="hljs-attr">data</span>: &#123;</span><br><span class="language-javascript">          <span class="hljs-comment">// 2️⃣-④：接收的第二个参数 data，它指的是数据；</span></span><br><span class="language-javascript"></span><br><span class="language-javascript">          <span class="hljs-attr">content</span>: <span class="hljs-string">&quot;hello world&quot;</span> <span class="hljs-comment">/*</span></span><br><span class="hljs-comment"><span class="language-javascript">          											 2️⃣-⑤：定义一个叫 content 的数据，内容是“hello world”，</span></span><br><span class="hljs-comment"><span class="language-javascript">          											 与原生的作区分。</span></span><br><span class="hljs-comment"><span class="language-javascript">                                  */</span>,</span><br><span class="language-javascript">        &#125;,</span><br><span class="language-javascript">      &#125;);</span><br><span class="language-javascript">    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>嘿，还搞不明白 Vue.js 的下载了。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/codingLei/article/details/136972476">如何在官网外找到并下载 Vue.js：CDN 方法详解-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://www.runoob.com/vue2/vue-install.html">Vue.js 安装 | 菜鸟教程 (runoob.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://worktile.com/kb/p/3611083">vue 源码如何下载 • Worktile 社区</a></p>
<h2 id="Node-体系"><a href="#Node-体系" class="headerlink" title="Node 体系"></a>Node 体系</h2><blockquote>
<p>2024 年 9 月 23 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7410668201778528275">Node.js 知识体系(一)：基础概念、历史与应用场景 Nodejs 的概念 Node.js 是一个基于 Chrome - 掘金 (juejin.cn)</a></p>
<blockquote>
<p>2025 年 1 月 15 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7129558664083406862">Github Actions 构建 Node.js 项目的 CICD 流水线本文介绍了 CI / CD 的概念， 主要是 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7125262744793645064">Node.js 入门（1）：安装和简介携手创作，共同成长！这是我参与「掘金日新计划 · 8 月更文挑战」的第 1 天，点击查看 - 掘金 (juejin.cn)</a></p>
<h2 id="桌面开发"><a href="#桌面开发" class="headerlink" title="桌面开发"></a>桌面开发</h2><blockquote>
<p>2024 年 9 月 23 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7136367341536804871">Electron 小白入门手册——跨端桌面应用开发的前世今生简史今天我们就从原生桌面开发、QT、NW、Electron、 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7366185126801637411">用 Electron 创建你的第一个应用程序：入门指南 Electron 是一个强大的开源框架，可以帮助开发人员使用 we - 掘金 (juejin.cn)</a></p>
<blockquote>
<p>2025 年 1 月 16 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_65635427/article/details/130780280?ops_request_misc=%7B%22request_id%22:%22a296ef507f5328a3e40dac4c6134641e%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=a296ef507f5328a3e40dac4c6134641e&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-130780280-null-null.142%5Ev101%5Econtrol&utm_term=qt%E6%95%99%E7%A8%8B&spm=1018.2226.3001.4187">QT 入门看这一篇就够了——超详细讲解（40000 多字详细讲解，涵盖 qt 大量知识）-CSDN 博客</a></p>
<h2 id="安卓开发"><a href="#安卓开发" class="headerlink" title="安卓开发"></a>安卓开发</h2><blockquote>
<p>2024 年 9 月 23 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7376937268215463975">Flutter 入门概览 1-Flutter 篇本系列文章共有三篇，计划分别从 Flutter、Dart、工具三个方面介绍，快速 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/6844903650704244750">Flutter 完整开发实战详解(一、Dart 语言和 Flutter 基础) | 掘金技术征文在如今的 Flutter 大潮下 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/6844903885413285902">带你高效入门 Flutter 本文面向 Flutter 初学者，旨在用易懂的方式带大家入门。除了 Flutter 代码，还 - 掘金 (juejin.cn)</a></p>
<h2 id="CodeForge"><a href="#CodeForge" class="headerlink" title="CodeForge"></a>CodeForge</h2><blockquote>
<p>2024 年 9 月 30 日</p>
</blockquote>
<p>一周前的今天，也就是二十三号下午，心里第一次有了这个计划的雏形。</p>
<p>趁着这次长假，好好打磨下平日里没工夫钻研的技术，或者也可以称之为爱好、兴趣，不过这些都已经无所谓了。</p>
<p>我又有了两种新的想法：</p>
<p><strong>简历投递，约面想法，求职。</strong></p>
<p><strong>持续精进，技术提升，兴趣。</strong></p>
<p>首先是最近两个月一直在关注着的秋招，简历优化，网申投递，面试邀约，做不完的测评和笔试，遥遥无期的 offer……</p>
<p>刚来到这里的前两周周末里还回小马村那边，在家的时候就能静下心来好好优化简历，八月十七号那天晚上第一次做出了两页版简历。</p>
<p>从那天晚上开始，便进入了紧锣密鼓的简历网申投递中去，同时简历迭代的周期也越来越短。</p>
<p>八月二十六号，八月二十九号，九月六号，九月九号，九月十四号，九月十九号，九月二十一号，九月二十二号，九月二十九号……</p>
<p>最终的简历模板已经在昨天晚上定型，目前暂时还没有要继续迭代简历的打算，估计这是最终版，但这会儿谁又能真正说清楚呢。</p>
<p>随着简历迭代趋于完善，网申计划也趋于完善。</p>
<p>自中秋节后以来，每天都保持网申投递至少 30 份简历的节奏，更多的时候一天能投递 80+份简历，这需要花费三四个小时左右的时间。</p>
<p>另外写了一篇文档提炼出网申阶段出现频率较高的填充内容，比如主修课程，校园经历，荣誉，兴趣爱好等，尽最大限度提高网申效率。</p>
<p>邮箱里陆陆续续收到了很多中大厂的测评和笔试邀请函，为了直观回顾秋招投递反馈日程，我设计了简要的 Excel 表格把这些记录下来。</p>
<p>这段时间里的测评和笔试倒是真不少，可邀约面试却根本没有，出了八月底的字节流程稍快一些，直到九月底才有水滴和捷顺科技约面。</p>
<p>约面很不顺利。</p>
<p>长达一个多月没有流程推进的时间里，我一直在实习僧，智联招聘和牛客直推上尝试沟通和邀约面试，为即将到来的秋招流程做足准备。</p>
<p>这方面我做得很漂亮，思路也确实正确。</p>
<p>我接到了更多的电话邀约，微信推送，邮箱链接，尽可能从更多的渠道获取面试资质，即便最终的结果一定是肯定的。</p>
<p>我决心要在这场秋招中拿下真正的入职 offer，尽管时间可能花费的比我想象中的还要久。</p>
<p>每周两到三个面试已经成为了家常便饭，在这样的环境下能约到面试本身就是件不容易的事情，我每次都能打起十二分的精神去应对。</p>
<p>从刚开始在等待中就惶恐不安，到后来面对面交流的从容不迫，我已经做到可以完全不惧任何面试情景了。</p>
<p>在这期间还特意总结了一篇面试文档，专门记录了面试流程中的各个环节表达要点，自我介绍，项目介绍，项目亮点分析这些。</p>
<p>当然，每场面试结束后都会快速回忆并产出一段面经要点，这些面经记录均已收录在我的真实面经文档中。</p>
<p>这就是我的网申阶段，这段生活确实有些麻木不仁和无可奈何，但无论如何网申还得继续，每多投出一份网申简历就多一分机会。</p>
<p>尽管目前已知的被收纳进人才库的企业，已经超过了五十家，剩下的都做过了测评和笔试后杳无音讯，我相信更多的都还在初筛流程中。</p>
<p>直到昨天晚上，我确乎认真考虑了一番，节后的求职阶段，在其他求职 APP 上也可以找找机会，机会还是挺多的。</p>
<p>有关求职的话题就暂且谈论到这里，后续如果还有更多突破性的进展，我倒是可以考虑在这里记录。</p>
<p>最近这段日子也确实在争分夺秒中考量之后的学习节奏，而不仅仅是应对即将到来的长假，更是为以后平稳的技术精进打下良好的基础。</p>
<p>不知道要学些什么，那当然不打紧，这都什么年代了网上什么都有，上稀土掘金胡乱看两小时就保证会有很多新奇想法。</p>
<p>我这里就不过多废话，直截了当地排列下最近或者说计划长期付诸的实践，也许能保质保量地贯彻下去：</p>
<figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-bullet">1.</span> AI 人工智能：这方面相对来讲比较轻松且有创造性，也是我最感兴趣的一部分，讯飞星火，ChatGPT，通义灵码，智能图书，智谱清言。<br></code></pre></td></tr></table></figure>

<figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs arduino"><span class="hljs-number">2.</span> 技术攻关：这方面可能要花费的时间精力会比较多，我想要写一些 Demo 代码来加强巩固这方面的知识，最好能写成系列博客，像拦截器/限流器，限流算法，函数式编程，SpringMVC 扩展点，<span class="hljs-built_in">Stream</span> 流，JWT 实践，WebSocket 实践，生产者消费者实现，消息队列，Guava，Mybatis-Plus 等等，后续有新的内容也会及时补充进来。<br></code></pre></td></tr></table></figure>

<figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-bullet">3.</span> 博文阅读：以上技术攻关的要点，都是最近看到的技术博客提供的新思路，除了公众号进阶笔记，苏三说技术，小报童专栏这些，稀土掘金上最近也喜欢看首页热门文章，又会关注到很多优秀的专栏。<br></code></pre></td></tr></table></figure>

<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-number">4</span>. 项目实践：这里讲到的开源项目，比如 AI 智能图书管理，仿<span class="hljs-selector-tag">B</span>站项目这样的，更多地想要在秋招备战阶段尽可能地巩固编码基础，切不可忘记手上功夫，不过就跟上面谈到的，首页热门文章也带给了我很多新想法，比如 Github 热点速递这些确实打开了我的思路。<br></code></pre></td></tr></table></figure>

<figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs reasonml"><span class="hljs-number">5.</span> 技术扩展：有哪些新的思路呢，我越发对桌面开发，Android 开发，游戏开发这些感兴趣了，百忙之中也会抽出时间来学习了解相关技术，权当作是消遣，<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Node</span>.</span></span>js，<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Vue</span>.</span></span>js，<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">React</span>.</span></span>js，Electron，Tarui，Flutter，.Net，C# 等。<br></code></pre></td></tr></table></figure>

<figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-bullet">6.</span> 小程序：这个单独拎出来作为一个栏目，是因为这方面以前也做过实操，这次区别于以上观望的态度，我更想做一些真正产品，学习了解小程序的部署上线，我觉得最近关注的那位大佬的专栏会帮助我实现这项愿望的。<br></code></pre></td></tr></table></figure>

<figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-bullet">7.</span> 项目部署：这个可以说是重中之重，我不做过多强调，Linux 环境，Docker 部署，程序员鱼皮教学视频。<br></code></pre></td></tr></table></figure>

<figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs markdown"><span class="hljs-bullet">8.</span> 博客优化：尽管没有新的博文，但壁纸还是要收集，乱序的博客内容也要稍作整理，还有七牛云老是欠费可不太好。<br></code></pre></td></tr></table></figure>

<p>呐，简单的计划已经罗列出来，如此看来任务还是蛮多的，就看七天以后的造化了。</p>
<p>玩不会想到写这玩意儿竟会花费我一个半小时的时间，不过现在心里面确实明朗了不少，祝我顺利吧，假期里也要保持最佳状态。</p>
<p>不过也要注意休息啊，劳逸结合嘛，在最紧张的阶段也要允许自己枯萎几天。</p>
<p><strong>祝假期愉快，愿前程景气，望仕途顺利。</strong></p>
<h2 id="鸿蒙"><a href="#鸿蒙" class="headerlink" title="鸿蒙"></a>鸿蒙</h2><blockquote>
<p>2025 年 1 月 15 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-hello-world-V5">创建和运行 Hello World-快速开始-DevEco Studio - 华为 HarmonyOS 开发者 (huawei.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7329034439408615451">🔥2024年最好用的 uniapp 开发模板 unibest，近一个月 star 数飙升！🔥🔥2024年最好用的 - 掘金</a></p>
<p><a target="_blank" rel="noopener" href="https://gitee.com/activity/2025opensource">Gitee 2025 年度开源项目</a></p>
<p><a target="_blank" rel="noopener" href="https://unibest.tech/">unibest 官方文档</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7020680215009427470?searchId=2025102821032485C173BFB181C201E382">😭血泪合集！uniapp小程序开发的超长实践总结！在经历了多个uniapp小程序项目开发后，我将我大量的踩坑实战经验复 - 掘金</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/6961663378083282951?searchId=2025102821032485C173BFB181C201E382">uniapp干货都在这了尤大上周末在视频号直播提到uniapp，表示还不错，而且他与dcloud团队有保持沟通，会给出自 - 掘金</a></p>
<h2 id="Uniapp"><a href="#Uniapp" class="headerlink" title="Uniapp"></a>Uniapp</h2><blockquote>
<p>2025 年 10 月 28 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/column/7070045934851194911">uni-app 应用开发 - 前端梦工厂的专栏 - 掘金</a></p>
<blockquote>
<p>2025 年 4 月 27 日</p>
</blockquote>
<p>振奋人心的消息。</p>
<p>创建订单，携带参数，跳转至创建订单页面。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//创建订单</span><br>			<span class="hljs-title function_">createOrder</span>(<span class="hljs-params"></span>) &#123;<br>				<span class="hljs-keyword">let</span> list = <span class="hljs-variable language_">this</span>.<span class="hljs-property">cartList</span>;<br>				<span class="hljs-keyword">let</span> cartIds = [];<br>				list.<span class="hljs-title function_">forEach</span>(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> &#123;<br>					<span class="hljs-keyword">if</span> (item.<span class="hljs-property">checked</span>) &#123;<br>						cartIds.<span class="hljs-title function_">push</span>(item.<span class="hljs-property">id</span>);<br>					&#125;<br>				&#125;)<br>				<span class="hljs-keyword">if</span>(cartIds.<span class="hljs-property">length</span>==<span class="hljs-number">0</span>)&#123;<br>					uni.<span class="hljs-title function_">showToast</span>(&#123;<br>						<span class="hljs-attr">title</span>:<span class="hljs-string">&#x27;您还未选择要下单的商品！&#x27;</span>,<br>						<span class="hljs-attr">duration</span>:<span class="hljs-number">1000</span><br>					&#125;)<br>					<span class="hljs-keyword">return</span>;<br>				&#125;<br>				uni.<span class="hljs-title function_">navigateTo</span>(&#123;<br>					<span class="hljs-attr">url</span>: <span class="hljs-string">`/pages/order/createOrder?cartIds=<span class="hljs-subst">$&#123;<span class="hljs-built_in">JSON</span>.stringify(cartIds)&#125;</span>`</span><br>				&#125;)<br>			&#125;<br></code></pre></td></tr></table></figure>

<p>创建订单页面，收货地址，商品信息，优惠信息。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;view&gt;<br>		&lt;!-- 地址 --&gt;<br>		&lt;navigator url=&quot;/pages/address/address?source=1&quot; class=&quot;address-section&quot;&gt;<br>			&lt;view class=&quot;order-content&quot;&gt;<br>				&lt;text class=&quot;yticon icon-shouhuodizhi&quot;&gt;&lt;/text&gt;<br>				&lt;view class=&quot;cen&quot;&gt;<br>					&lt;view class=&quot;top&quot;&gt;<br>						&lt;text class=&quot;name&quot; v-if=&quot;currentAddress.name&quot;&gt;&#123;&#123;currentAddress.name&#125;&#125;&lt;/text&gt;<br>						&lt;text class=&quot;mobile&quot; v-if=&quot;currentAddress.phoneNumber&quot;&gt;&#123;&#123;currentAddress.phoneNumber&#125;&#125;&lt;/text&gt;<br>					&lt;/view&gt;<br>					&lt;text class=&quot;address&quot;&gt;&#123;&#123;currentAddress.province&#125;&#125; &#123;&#123;currentAddress.city&#125;&#125; &#123;&#123;currentAddress.region&#125;&#125;<br>						&#123;&#123;currentAddress.detailAddress&#125;&#125;&lt;/text&gt;<br>				&lt;/view&gt;<br>				&lt;text class=&quot;yticon icon-you&quot;&gt;&lt;/text&gt;<br>			&lt;/view&gt;<br><br>			&lt;image class=&quot;a-bg&quot;<br>			&lt;/image&gt;<br>		&lt;/navigator&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;view class=&quot;goods-section&quot;&gt;<br>			&lt;view class=&quot;g-header b-b&quot;&gt;<br>				&lt;text class=&quot;name&quot;&gt;商品信息&lt;/text&gt;<br>			&lt;/view&gt;<br>			&lt;!-- 商品列表 --&gt;<br>			&lt;text&gt;调试数据: &#123;&#123; cartPromotionItemList &#125;&#125;&lt;/text&gt;<br>			&lt;text&gt;调试数据: &#123;&#123; cartPromotionItemList.length &#125;&#125;&lt;/text&gt;<br>			&lt;view class=&quot;g-item&quot; v-for=&quot;item in cartPromotionItemList&quot; :key=&quot;item.id&quot;&gt;<br>				&lt;image :src=&quot;item.productPic&quot;&gt;&lt;/image&gt;<br>				&lt;view class=&quot;right&quot;&gt;<br>					&lt;text class=&quot;title clamp&quot;&gt;&#123;&#123;item.productName&#125;&#125;&lt;/text&gt;<br>					&lt;text class=&quot;spec&quot;&gt;&#123;&#123;item.productAttr | formatProductAttr&#125;&#125;&lt;/text&gt;<br>					&lt;text class=&quot;promotion clamp&quot;&gt;&#123;&#123;item.promotionMessage&#125;&#125;&lt;/text&gt;<br>					&lt;view class=&quot;price-box&quot;&gt;<br>						&lt;text class=&quot;price&quot;&gt;￥&#123;&#123;item.price&#125;&#125;&lt;/text&gt;<br>						&lt;text class=&quot;number&quot;&gt;x &#123;&#123;item.quantity&#125;&#125;&lt;/text&gt;<br>					&lt;/view&gt;<br>				&lt;/view&gt;<br>			&lt;/view&gt;<br>		&lt;/view&gt;<br></code></pre></td></tr></table></figure>

<p>发起请求。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-title function_">data</span>(<span class="hljs-params"></span>) &#123;<br>			<span class="hljs-keyword">return</span> &#123;<br>				<span class="hljs-attr">maskState</span>: <span class="hljs-number">0</span>, <span class="hljs-comment">//优惠券面板显示状态</span><br>				<span class="hljs-attr">desc</span>: <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-comment">//备注</span><br>				<span class="hljs-attr">payType</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">//1微信 2支付宝</span><br>				<span class="hljs-attr">couponList</span>: [],<br>				<span class="hljs-attr">memberReceiveAddressList</span>: [],<br>				<span class="hljs-attr">currentAddress</span>: &#123;&#125;,<br>				<span class="hljs-attr">cartPromotionItemList</span>: [],<br>				<span class="hljs-attr">calcAmount</span>: &#123;&#125;,<br>				<span class="hljs-attr">currCoupon</span>: <span class="hljs-literal">null</span>,<br>				<span class="hljs-attr">useIntegration</span>: <span class="hljs-number">0</span>,<br>				<span class="hljs-attr">integrationConsumeSetting</span>: &#123;&#125;,<br>				<span class="hljs-attr">memberIntegration</span>: <span class="hljs-number">0</span>,<br>				<span class="hljs-attr">cartIds</span>: []<br>			&#125;<br>		&#125;,<br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-title function_">onLoad</span>(<span class="hljs-params">option</span>) &#123;<br>			<span class="hljs-comment">//商品数据</span><br>			<span class="hljs-variable language_">this</span>.<span class="hljs-property">cartIds</span> = <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">parse</span>(option.<span class="hljs-property">cartIds</span>);<br>			<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;+++&quot;</span> + <span class="hljs-variable language_">this</span>.<span class="hljs-property">cartIds</span>)<br>			<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">loadData</span>();<br>		&#125;,<br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//生成确认单信息</span><br>			<span class="hljs-keyword">async</span> <span class="hljs-title function_">loadData</span>(<span class="hljs-params"></span>) &#123;<br>				<span class="hljs-variable language_">this</span>.<span class="hljs-property">isLoading</span> = <span class="hljs-literal">true</span>;<br>				<span class="hljs-keyword">try</span> &#123;<br>					<span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> <span class="hljs-title function_">generateConfirmOrder</span>(<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">cartIds</span>));<br>					<span class="hljs-keyword">const</span> res = response.<span class="hljs-property">data</span>;<br><br>					<span class="hljs-comment">// 使用 Vue.set 或展开运算符确保响应式更新</span><br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">cartPromotionItemList</span> = [...res.<span class="hljs-property">cartPromotionItemList</span>]; <span class="hljs-comment">// 深拷贝数组</span><br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">currentAddress</span> = &#123;<br>						...<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">getDefaultAddress</span>()<br>					&#125;; <span class="hljs-comment">// 确保地址是响应式</span><br><br>					uni.$emit(<span class="hljs-string">&#x27;updateData&#x27;</span>, &#123;<br>						<span class="hljs-attr">list</span>: res.<span class="hljs-property">cartPromotionItemList</span><br>					&#125;);<br><br>					<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;购物车数据:&quot;</span>, <span class="hljs-variable language_">this</span>.<span class="hljs-property">cartPromotionItemList</span>); <span class="hljs-comment">// 确认数据格式</span><br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">memberReceiveAddressList</span> = res.<span class="hljs-property">memberReceiveAddressList</span>;<br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">currentAddress</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">getDefaultAddress</span>();<br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">couponList</span> = [];<br>					<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> item <span class="hljs-keyword">of</span> res.<span class="hljs-property">couponHistoryDetailList</span>) &#123;<br>						<span class="hljs-variable language_">this</span>.<span class="hljs-property">couponList</span>.<span class="hljs-title function_">push</span>(item.<span class="hljs-property">coupon</span>);<br>					&#125;<br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">calcAmount</span> = res.<span class="hljs-property">calcAmount</span>;<br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">integrationConsumeSetting</span> = res.<span class="hljs-property">integrationConsumeSetting</span>;<br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">memberIntegration</span> = res.<span class="hljs-property">memberIntegration</span>;<br>				&#125; <span class="hljs-keyword">catch</span> (err) &#123;<br>					<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&quot;加载数据失败:&quot;</span>, err);<br>					uni.<span class="hljs-title function_">showToast</span>(&#123;<br>						<span class="hljs-attr">title</span>: <span class="hljs-string">&quot;加载失败&quot;</span>,<br>						<span class="hljs-attr">icon</span>: <span class="hljs-string">&quot;none&quot;</span><br>					&#125;);<br>				&#125; <span class="hljs-keyword">finally</span> &#123;<br>					<span class="hljs-variable language_">this</span>.<span class="hljs-property">isLoading</span> = <span class="hljs-literal">false</span>;<br>					<span class="hljs-variable language_">this</span>.$forceUpdate(); <span class="hljs-comment">// 强制重新渲染</span><br>				&#125;<br><br>			&#125;,<br></code></pre></td></tr></table></figure>

<p>这段代码，废了我俩小时总算检索出来了。控制台报错就是这里。购物车地址转换失败，接下来的数据就没有解析。</p>
<p>整个过滤器钩子函数执行中断。</p>
<p>艹。</p>
<p><img src="http://blog.memory-life.xyz/image-20250427193544980.png" alt="image-20250427193544980"></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-attr">filters</span>: &#123;<br>			<span class="hljs-title function_">formatProductAttr</span>(<span class="hljs-params">jsonAttr</span>) &#123;<br>				<span class="hljs-keyword">let</span> attrArr = <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">parse</span>(jsonAttr);<br>				<span class="hljs-keyword">let</span> attrStr = <span class="hljs-string">&#x27;&#x27;</span>;<br>				<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> attr <span class="hljs-keyword">of</span> attrArr) &#123;<br>					attrStr += attr.<span class="hljs-property">key</span>;<br>					attrStr += <span class="hljs-string">&quot;:&quot;</span>;<br>					attrStr += attr.<span class="hljs-property">value</span>;<br>					attrStr += <span class="hljs-string">&quot;;&quot;</span>;<br>				&#125;<br>				<span class="hljs-keyword">return</span> attrStr<br>			&#125;,<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250427193019459.png"></p>
<blockquote>
<p>2025 年 1 月 15 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/article/2409070">自己开发的 App 如何上架，详细解读 App 上架操作流程-腾讯云开发者社区-腾讯云 (tencent.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/article/2365581">uniapp 开发 App 从开发到上架全过程-腾讯云开发者社区-腾讯云 (tencent.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/JiayaoXu/article/details/128453091">uniapp 开发 APP 从开发到上架全过程（一）-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/JiayaoXu/article/details/128467553">uniapp 开发 App 从开发到上架全过程(二)-真机调试_uniapp ios 真机调试-CSDN 博客</a></p>
<h2 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h2><blockquote>
<p>2025 年 11 月 10 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7106484991483183118?searchId=202511101834583DDBEC6B3652F3010033">Linux安装Docker详细教程！ 本文已参与「新人创作礼」活动，一起开启掘金创作之路。 前置条件 前置知识 1、 - 掘金</a></p>
<blockquote>
<p>2024 年 12 月 19 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_39135287/article/details/101012149">Docker 入门到实践 (一) docker 简介与安装_docker 与思政-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_39135287/article/details/102955902">Docker 入门到实践 (二) docker 常用命令讲解_docker 入门到实践 (二) docker 常用指令解说-CSDN 博客</a></p>
<blockquote>
<p>2025 年 1 月 15 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/article/1701451">centos7 安装 Docker 详细步骤（无坑版教程）-腾讯云开发者社区-腾讯云 (tencent.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://config.net.cn/server/microservice/c295646a-b68a-48b6-a0a3-a3c829e6a64d-p1.html">windows10+VMWare+Centos7 下 docker 的安装，验证与运行(超详细且持续更新) -配置啦-研发运维人员必备网站 (config.net.cn)</a></p>
<p><a target="_blank" rel="noopener" href="http://mirrors.aliyun.com/centos/">centos 安装包下载_开源镜像站-阿里云 (aliyun.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://config.net.cn/server/microservice/c295646a-b68a-48b6-a0a3-a3c829e6a64d-p1.html">windows10+VMWare+Centos7 下 docker 的安装，验证与运行(超详细且持续更新) -配置啦-研发运维人员必备网站 (config.net.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7203258813893345340">Docker 搭建 Minio 对象存储服务 MinIO MinIO 是一款基于 Go 语言发开的高性能、分布式的对象存储 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7165372823467196423">手摸手教你使用 Docker 快速搭建 Gitlab 服务本文在 CentOS 虚拟机中使用 Docker 快速搭建了一 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7146440835381329934">上手 Linux：安装 Git 的两种方式在 Linux 系统上安装软件有两种常用的方式。一种是下载源码 - 编译 - 安 - 掘金 (juejin.cn)</a></p>
<p>这篇挺全的：<a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1725379904230518786#heading-22">Springboot 整合 Minio 全流程 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<blockquote>
<p>2025 年 1 月 25 日</p>
</blockquote>
<p>今天实践操作下 docker，安装 Docker。</p>
<h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p><strong>查看 CentOS 操作系统版本和 Linux 内核版本</strong>：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">cat</span> /etc/redhat-release<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">uname</span> -r<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250125193326081.png" alt="image-20250125193326081"></p>
<p>可以看到 CentOS7 的操作系统为 x86_64(64 位)，系统内核版本为 3.10.0，没有问题。</p>
<p><strong>卸载旧版本。</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine<br></code></pre></td></tr></table></figure>

<p><img src="C:/Users/Lenovo/AppData/Roaming/Typora/typora-user-images/image-20250125193531866.png" alt="image-20250125193531866"></p>
<p><strong>安装 docker 所需的软件包</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install -y yum-utils device-mapper-persistent-data lvm2<br></code></pre></td></tr></table></figure>

<p><strong>设置 yum 源为阿里云 (由于国外网站访问速度慢)</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo<br></code></pre></td></tr></table></figure>

<p><strong>更新 yum 软件包索引</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum makecache fast<br></code></pre></td></tr></table></figure>

<p><strong>安装 docker CE(社区版)，Docker 提供了两个版本：社区版(CE，免费) 和 企业版(EE，收费)</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y install docker-ce<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_44700578/article/details/140881224">Linux 中 yum、rpm、apt-get、wget 的区别，yum、rpm、apt-get 常用命令，CentOS、Ubuntu 中安装 wget_apt-get 和 yum-CSDN 博客</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250125194344413.png" alt="image-20250125194344413"></p>
<p>检查版本，是否安装成功。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker version<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250125194522470.png" alt="image-20250125194522470"></p>
<blockquote>
<p>2025 年 1 月 25 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_39135287/article/details/102955902">Docker 入门到实践 (二) docker 常用命令讲解_docker 入门到实践 (二) docker 常用指令解说-CSDN 博客</a></p>
<blockquote>
<p>2025 年 2 月 10 日</p>
</blockquote>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum install -y yum-utils device-mapper-persistent-data lvm2<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">ping: mirrorlist.centos.org: Name or service not known<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_46122805/article/details/143656526">CentOS7 yum 安装报错 “Could not resolve host: mirrorlist.centos.org； Name or service not known” 解决方法_ping: mirrorlist.centos.org: name or service not k-CSDN 博客</a></p>
<p>1、从阿里云下载新的配置文件，两个命令可用，如果虚拟机还没安装 wget 工具，就使用 curl</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo<br>curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo<br></code></pre></td></tr></table></figure>

<p>2、清理缓存</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum clean all<br></code></pre></td></tr></table></figure>

<p>3、重新生成缓存</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum makecache<br></code></pre></td></tr></table></figure>

<p>4、更新 yum 源包</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yum -y update<br></code></pre></td></tr></table></figure>

<p>结束，更换 yum 源成功。</p>
<p>不过这个步骤属实多余，直接按照上面 Doker 安装的命令执行下来，安装 Docker 是相当顺利的。</p>
<h3 id="远程部署"><a href="#远程部署" class="headerlink" title="远程部署"></a>远程部署</h3><blockquote>
<p>2025 年 2 月 5 日</p>
</blockquote>
<p>已经十多天没有学习了吗。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_62128476/article/details/144411765">Docker 为容器设置环境变量（在 docker run 命令中设置容器的环境变量、在 Dockerfile 文件中设置容器的环境变量、在 docker-compose.yaml 中设置容器的环境变量）_dockerfile 设置环境变量-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.51cto.com/u_16175488/11781019">java 获取 docker 环境变量_mob649e8161738c 的技术博客_51CTO 博客</a></p>
<p>新建一个 Web 项目，尝试下 Docker 部署。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_36833673/article/details/145308820">docker 部署 java 项目详解-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/cuay/p/18501288">WAR 包和 JAR 包的区别 - 林泽阿 - 博客园 (cnblogs.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1776245631845789697#heading-4">IDEA+Docker 远程部署 Sprin - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile"><span class="hljs-comment"># 基础镜像</span><br><span class="hljs-keyword">FROM</span> openjdk:<span class="hljs-number">8</span><br><span class="hljs-comment"># 复制主机jar包至镜像内，复制的目录需放置在 Dockerfile 文件同级目录下</span><br><span class="hljs-keyword">ADD</span><span class="language-bash"> target/hello-0.0.1-SNAPSHOT.jar app.jar</span><br><span class="hljs-comment"># 容器启动执行命令</span><br><span class="hljs-keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="hljs-string">&quot;java&quot;</span>,<span class="hljs-string">&quot;-jar&quot;</span>, <span class="hljs-string">&quot;/app.jar&quot;</span> , <span class="hljs-string">&quot;--spring.profiles.active=prod&quot;</span>]</span><br><span class="hljs-comment"># 对外暴露的端口号</span><br><span class="hljs-keyword">EXPOSE</span>  <span class="hljs-number">8080</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1872492636669014017#heading-3">Docker 一键远程部署厚米匹配后端 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs angelscript"><span class="hljs-symbol">Dw990831@</span><br></code></pre></td></tr></table></figure>

<p>配置 Docker 一键部署：ssh 远程连接服务器，连接 Docker 守护进程，编写 Dockerfile 文件，配置远程部署。</p>
<p>ssh 远程连接服务器。</p>
<p><img src="http://blog.memory-life.xyz/image-20250205102013411.png" alt="image-20250205102013411"></p>
<p>连接 Docker 守护进程。</p>
<p><img src="http://blog.memory-life.xyz/image-20250205103921071.png" alt="image-20250205103921071"></p>
<p>编写 Dockerfile 文件。</p>
<figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile"><span class="hljs-comment"># 基础镜像</span><br><span class="hljs-keyword">FROM</span> openjdk:<span class="hljs-number">8</span><br><span class="hljs-comment"># 复制主机jar包至镜像内，复制的目录需放置在 Dockerfile 文件同级目录下</span><br><span class="hljs-keyword">ADD</span><span class="language-bash"> target/hello-0.0.1-SNAPSHOT.jar app.jar</span><br><span class="hljs-comment"># 容器启动执行命令</span><br><span class="hljs-keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="hljs-string">&quot;java&quot;</span>,<span class="hljs-string">&quot;-jar&quot;</span>, <span class="hljs-string">&quot;/app.jar&quot;</span>]</span><br><span class="hljs-comment"># 对外暴露的端口号</span><br><span class="hljs-keyword">EXPOSE</span>  <span class="hljs-number">8080</span><br></code></pre></td></tr></table></figure>

<p>配置远程部署。</p>
<p><img src="http://blog.memory-life.xyz/image-20250205103822292.png" alt="image-20250205103822292"></p>
<p><a target="_blank" rel="noopener" href="https://blog.51cto.com/u_16213317/11768523">怎么查看 docker 开放的端口通不通_mob64ca12d4a164 的技术博客_51CTO 博客</a></p>
<p>特么的，配置都完成了，就看最后一步能不能一键部署成功，结果好像是 Docker 连接失败了。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_67497257/article/details/140822980">Docker 镜像的创建方法_docker 创建镜像-CSDN 博客</a></p>
<p>那就手动上传 jar 包和 Dockerfile 文件，先构建镜像再运行容器试试看。</p>
<p>学一学。</p>
<p>要构建一个 Docker 镜像，你需要确保你已经安装了 Docker，并且你的<code>Dockerfile</code>和<code>hello-0.0.1-SNAPSHOT.jar</code>文件在同一目录下。以下是如何使用 Docker 命令行工具来构建你的镜像的步骤：</p>
<ol>
<li><p><strong>打开命令行界面</strong>：</p>
<ul>
<li>在 Windows 上，你可以使用 PowerShell 或命令提示符。</li>
<li>在 macOS 或 Linux 上，打开你的终端。</li>
</ul>
</li>
<li><p><strong>导航到包含 Dockerfile 的目录</strong>：<br>使用<code>cd</code>命令导航到包含你的<code>Dockerfile</code>和<code>hello-0.0.1-SNAPSHOT.jar</code>文件的目录。例如：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br><span class="hljs-built_in">cd</span> path/to/your/directory<br></code></pre></td></tr></table></figure></li>
<li><p><strong>构建 Docker 镜像</strong>：<br>使用<code>docker build</code>命令来构建你的镜像。你需要为你的镜像指定一个标签（tag），这通常包括一个名称和一个版本号。例如：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>docker build -t hello-app:0.0.1 .<br></code></pre></td></tr></table></figure>

<p>这里的<code>-t hello-app:0.0.1</code>指定了镜像的名称为<code>hello-app</code>和版本号为<code>0.0.1</code>。最后的<code>.</code>表示 Dockerfile 位于当前目录。</p>
</li>
<li><p><strong>验证镜像是否构建成功</strong>：<br>使用<code>docker images</code>命令来查看你的本地镜像列表，确认你的<code>hello-app:0.0.1</code>镜像已经成功构建。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>docker images<br></code></pre></td></tr></table></figure></li>
<li><p><strong>运行 Docker 容器</strong>：<br>使用<code>docker run</code>命令来运行你的容器。例如：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>docker run -d -p 8080:8080 hello-app:0.0.1<br></code></pre></td></tr></table></figure>

<p>这里的<code>-d</code>标志表示容器将在后台运行，<code>-p 8080:8080</code>将主机的 8080 端口映射到容器的 8080 端口。</p>
</li>
<li><p><strong>验证容器是否正在运行</strong>：<br>使用<code>docker ps</code>命令来查看正在运行的容器列表。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">bash复制代码<br><br>docker ps<br></code></pre></td></tr></table></figure></li>
<li><p><strong>访问你的应用</strong>：<br>打开你的网页浏览器，访问<code>http://localhost:8080</code>，你应该能够看到你的 Java 应用正在运行。</p>
</li>
</ol>
<p>试一试。</p>
<p>出问题了。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]<span class="hljs-comment"># docker build -f Dockerfile -t hello</span><br>ERROR: <span class="hljs-string">&quot;docker buildx build&quot;</span> requires exactly 1 argument.<br>See <span class="hljs-string">&#x27;docker buildx build --help&#x27;</span>.<br><br>Usage:  docker buildx build [OPTIONS] PATH | URL | -<br><br>Start a build<br>[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]<span class="hljs-comment"># docker build -t hello-app .</span><br>[+] Building 30.1s (2/2) FINISHED                                                                                                                                                docker:default<br> =&gt; [internal] load build definition from Dockerfile                                                                                                                                       0.0s<br> =&gt; =&gt; transferring dockerfile: 323B                                                                                                                                                       0.0s<br> =&gt; ERROR [internal] load metadata <span class="hljs-keyword">for</span> docker.io/library/openjdk:8                                                                                                                        30.0s<br>------<br> &gt; [internal] load metadata <span class="hljs-keyword">for</span> docker.io/library/openjdk:8:<br>------<br>Dockerfile:2<br>--------------------<br>   1 |     <span class="hljs-comment"># 基础镜像</span><br>   2 | &gt;&gt;&gt; FROM openjdk:8<br>   3 |     <span class="hljs-comment"># 复制主机jar包至镜像内，复制的目录需放置在 Dockerfile 文件同级目录下</span><br>   4 |     ADD target/hello-0.0.1-SNAPSHOT.jar app.jar<br>--------------------<br>ERROR: failed to solve: DeadlineExceeded: DeadlineExceeded: DeadlineExceeded: openjdk:8: failed to resolve <span class="hljs-built_in">source</span> metadata <span class="hljs-keyword">for</span> docker.io/library/openjdk:8: failed to <span class="hljs-keyword">do</span> request: Head <span class="hljs-string">&quot;https://registry-1.docker.io/v2/library/openjdk/manifests/8&quot;</span>: dial tcp 198.44.185.131:443: i/o <span class="hljs-built_in">timeout</span><br></code></pre></td></tr></table></figure>

<p>jar 包没有放在同级目录下啊。</p>
<p>算了，看来是基础镜像出问题了，吃完饭上来搞搞。</p>
<h3 id="镜像源修改"><a href="#镜像源修改" class="headerlink" title="镜像源修改"></a>镜像源修改</h3><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/ZPC8210/article/details/145176508">docker hello world_docker 输出 hello word-CSDN 博客</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker pull hello-world<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]<span class="hljs-comment"># docker pull hello-world</span><br>Using default tag: latest<br>Error response from daemon: Get <span class="hljs-string">&quot;https://registry-1.docker.io/v2/&quot;</span>: net/http: request canceled <span class="hljs-keyword">while</span> waiting <span class="hljs-keyword">for</span> connection (Client.Timeout exceeded <span class="hljs-keyword">while</span> awaiting headers)<br>[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]<span class="hljs-comment">#</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_51492817/article/details/140332408">Docker 修改国内镜像源_docker 更换国内镜像源-CSDN 博客</a></p>
<p>这篇写得很详细了：<a target="_blank" rel="noopener" href="https://blog.51cto.com/u_16213434/11776091">docker 切换国内镜像源_mob64ca12f10f72 的技术博客_51CTO 博客</a></p>
<p>使用 docker 命令行设置镜像源，不太好使。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">sudo docker login --username=&lt;你的用户名&gt; registry.cn-hangzhou.aliyuncs.com<br></code></pre></td></tr></table></figure>

<p>得直接修改 Docker 的 daemon 配置文件。</p>
<p>步骤详解</p>
<p>步骤 1: 备份 Docker 的原始配置文件。</p>
<p>在对 Docker 的配置文件进行修改之前，我们需要先备份原始配置文件，以便在出现问题时能够恢复。</p>
<p>备份原始的配置文件到指定位置</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">sudo <span class="hljs-built_in">cp</span> /etc/docker/daemon.json /etc/docker/daemon.json.bak<br></code></pre></td></tr></table></figure>

<p>代码解释：</p>
<ul>
<li><p>sudo：以超级用户权限执行命令。</p>
</li>
<li><p>cp：复制文件的命令。</p>
</li>
<li><p>/etc/docker/daemon.json：Docker 的默认配置文件路径。</p>
</li>
<li><p>/etc/docker/daemon.json.bak：备份文件的路径。</p>
</li>
</ul>
<p>步骤 2: 创建或编辑 Docker 的配置文件</p>
<p>确保 Docker 的配置文件存在，如果没有则需要创建一个新的。</p>
<p>检查配置文件是否存在</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">sudo <span class="hljs-built_in">mkdir</span> -p /etc/docker/<br>sudo <span class="hljs-built_in">touch</span> /etc/docker/daemon.json<br></code></pre></td></tr></table></figure>

<p>代码解释：</p>
<ul>
<li><p>mkdir -p /etc/docker/：创建 Docker 配置目录，如果路径中已存在部分目录则不会报错。</p>
</li>
<li><p>touch /etc/docker/daemon.json：创建 daemon.json 文件，如果已存在则更新其时间戳。</p>
</li>
</ul>
<p>步骤 3: 修改镜像源为国内镜像</p>
<p>接下来，我们需要通过编辑 daemon.json 文件来添加国内的镜像源。这里以阿里云的 Docker 镜像为例。</p>
<p>开启编辑器（vi 或其它文本编辑器）</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">sudo vi /etc/docker/daemon.json<br></code></pre></td></tr></table></figure>

<p>在打开的 daemon.json 文件中填写以下内容：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">&#123;<br>  <span class="hljs-string">&quot;registry-mirrors&quot;</span>: [<br>    <span class="hljs-string">&quot;https://&lt;your_ali_cdn&gt;.mirror.aliyuncs.com&quot;</span><br>  ]<br>&#125;<br></code></pre></td></tr></table></figure>

<p>代码解释：</p>
<ul>
<li><p>registry-mirrors：这是配置镜像加速器的键，用于指定 Docker 镜像源的地址。</p>
</li>
<li><p>“https://<your_ali_cdn>.mirror.aliyuncs.com”：将 <your_ali_cdn> 替换为你在阿里云中获得的加速器地址。你也可以选择其他的国内镜像源，如网易、腾讯等。</p>
</li>
</ul>
<p>步骤 4: 重启 Docker 服务</p>
<p>完成镜像源的配置后，我们需要重启 Docker 服务使其生效。</p>
<p>重启 Docker 服务</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">sudo systemctl daemon-reload<br>sudo systemctl restart docker<br></code></pre></td></tr></table></figure>

<p>代码解释：</p>
<ul>
<li><p>systemctl daemon-reload：重新加载服务配置。</p>
</li>
<li><p>systemctl restart docker：重启 Docker 服务。</p>
</li>
</ul>
<p>步骤 5: 验证镜像源是否修改成功</p>
<p>最后一步是验证配置是否成功。我们可以通过拉取一个镜像来检查。</p>
<p>测试拉取一个镜像（例如：hello-world）</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker pull hello-world<br></code></pre></td></tr></table></figure>

<p>代码解释：</p>
<ul>
<li>docker pull hello-world：从 Docker 镜像源拉取 hello-world 镜像，用于测试。</li>
</ul>
<p>如果镜像能够快速拉取并成功完成，那么就表示你已成功切换至国内镜像源。</p>
<p><a target="_blank" rel="noopener" href="http://www.llxxkj.cn/content/1939.html">阿里云地域 Region ID? 地域及其 RegionID 对照表?_陆陆科技 (llxxkj.cn)</a></p>
<p><img src="http://www.llxxkj.cn/data/upload/2023-06-29/649d1f91988cd.png" alt="649d1f91988cd.png"></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">&#123;<br>  <span class="hljs-string">&quot;registry-mirrors&quot;</span>: [<br>    <span class="hljs-string">&quot;https://cn-beijing.mirror.aliyuncs.com&quot;</span><br>  ]<br>&#125;<br></code></pre></td></tr></table></figure>

<p>漂亮，对照这张表修改配置文件内容，直接执行拉取镜像命令，成功了。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@iZ2ze4hnl6pls28qt4w1ttZ docker]<span class="hljs-comment"># docker pull hello-world</span><br>Using default tag: latest<br>latest: Pulling from library/hello-world<br>2db29710123e: Pull complete<br>Digest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f<br>Status: Downloaded newer image <span class="hljs-keyword">for</span> he<br></code></pre></td></tr></table></figure>

<p>那么跑一下这个镜像吧。</p>
<p>运行一个名为 <code>hello-world</code> 的镜像，容器名为 <code>helloworld</code>，将容器的 80 端口映射到主机的 8080 端口，并在后台运行：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker run -d -p 8080:80 --name helloworld hello-world:latest<br></code></pre></td></tr></table></figure>

<p>查看正在运行中的容器信息。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker ps -a<br></code></pre></td></tr></table></figure>

<figure class="highlight autoit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs autoit">[root<span class="hljs-symbol">@iZ2ze4hnl6pls28qt4w1ttZ</span> serInfo]<span class="hljs-meta"># docker ps -a</span><br>CONTAINER ID   IMAGE                COMMAND    CREATED         STATUS                     PORTS     NAMES<br>cb2146386e71   hello-world:latest   <span class="hljs-string">&quot;/hello&quot;</span>   <span class="hljs-number">3</span> minutes ago   Exited (<span class="hljs-number">0</span>) <span class="hljs-number">3</span> minutes ago             helloworld<br></code></pre></td></tr></table></figure>

<p>删除镜像。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docekr remove helloworld<br></code></pre></td></tr></table></figure>

<p>镜像源问题解决了，构建 Docker 镜像的报错问题还没有进展，检查下 Dockerfile 文件内容。</p>
<figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile"><span class="hljs-comment"># 基础镜像</span><br><span class="hljs-keyword">FROM</span> openjdk:<span class="hljs-number">8</span><br><span class="hljs-comment"># 复制主机jar包至镜像内，复制的目录需放置在 Dockerfile 文件同级目录下</span><br><span class="hljs-keyword">ADD</span><span class="language-bash"> target/hello-0.0.1-SNAPSHOT.jar app.jar</span><br><span class="hljs-comment"># 容器启动执行命令</span><br><span class="hljs-keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="hljs-string">&quot;java&quot;</span>,<span class="hljs-string">&quot;-jar&quot;</span>, <span class="hljs-string">&quot;/app.jar&quot;</span>]</span><br><span class="hljs-comment"># 对外暴露的端口号</span><br><span class="hljs-keyword">EXPOSE</span>  <span class="hljs-number">8080</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1831926133062430721">5 个提升你 Dockerfile 水平 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<p>Dockerfile 有挺多技巧：</p>
<ol>
<li>使用 alpine 的镜像，而不是默认的 linux 镜像，可以极大减小镜像体积，比如 node:18-alpine3.14 这种</li>
<li>使用多阶段构建，比如一个阶段来执行 build，一个阶段把文件复制过去，跑起服务来，最后只保留最后一个阶段的镜像。这样使镜像内只保留运行需要的文件以及 dependencies。</li>
<li>使用 ARG 增加构建灵活性，ARG 可以在 docker build 时通过 –build-arg xxx=yyy 传入，在 dockerfile 中生效，可以使构建过程更灵活。如果是想定义运行时可以访问的变量，可以通过 ENV 定义环境变量，值使用 ARG 传入。</li>
<li>CMD 和 ENTRYPOINT 都可以指定容器跑起来之后运行的命令，CMD 可以被覆盖，而 ENTRYPOINT 不可以，两者结合使用可以实现参数默认值的功能。</li>
<li>ADD 和 COPY 都可以复制文件到容器内，但是 ADD 处理 tar.gz 的时候，还会做一下解压。</li>
</ol>
<p><a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/article/2372154">Docker 镜像构建知识：Dockerfile 命令详解-腾讯云开发者社区-腾讯云 (tencent.com)</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 基础镜像</span><br>FROM scratch<br><span class="hljs-comment"># 复制主机jar包至镜像内，复制的目录需放置在 Dockerfile 文件同级目录下</span><br>ADD hello-0.0.1-SNAPSHOT.jar app.jar<br><span class="hljs-comment"># 容器启动执行命令</span><br>ENTRYPOINT [<span class="hljs-string">&quot;java&quot;</span>,<span class="hljs-string">&quot;-jar&quot;</span>, <span class="hljs-string">&quot;/app.jar&quot;</span>]<br><span class="hljs-comment"># 对外暴露的端口号</span><br>EXPOSE  8080<br></code></pre></td></tr></table></figure>

<p>构建成功了对吧。</p>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs ruby">[root<span class="hljs-variable">@iZ2ze4hnl6pls28qt4w1ttZ</span> serInfo]<span class="hljs-comment"># docker build -t hello-app .</span><br>[+] <span class="hljs-title class_">Building</span> <span class="hljs-number">0</span>.4s (<span class="hljs-number">5</span>/<span class="hljs-number">5</span>) <span class="hljs-variable constant_">FINISHED</span>   <span class="hljs-symbol">docker:</span>default<br> =&gt; [internal] load build definition from <span class="hljs-title class_">Dockerfile</span>   			    <span class="hljs-number">0</span>.0s<br> =&gt; =&gt; transferring <span class="hljs-symbol">dockerfile:</span> 313B                         		<span class="hljs-number">0</span>.0s<br> =&gt; [internal] load .dockerignore                                    <span class="hljs-number">0</span>.0s<br> =&gt; =&gt; transferring <span class="hljs-symbol">context:</span> 2B                                      <span class="hljs-number">0</span>.0s<br> =&gt; [internal] load build context                                    <span class="hljs-number">0</span>.2s<br> =&gt; =&gt; transferring <span class="hljs-symbol">context:</span> <span class="hljs-number">17</span>.65MB                                 <span class="hljs-number">0</span>.2s<br> =&gt; [<span class="hljs-number">1</span>/<span class="hljs-number">1</span>] <span class="hljs-variable constant_">ADD</span> hello-<span class="hljs-number">0.0</span>.<span class="hljs-number">1</span>-<span class="hljs-variable constant_">SNAPSHOT</span>.jar app.jar                       <span class="hljs-number">0</span>.0s<br> =&gt; exporting to image                                               <span class="hljs-number">0</span>.1s<br> =&gt; =&gt; exporting layers                                              <span class="hljs-number">0</span>.1s<br> =&gt; =&gt; writing image <span class="hljs-symbol">sha256:</span>19baea50ee1023afb4c6926836a32e3816a315de477db0fcf3d164e25b1ed5b2<br></code></pre></td></tr></table></figure>

<p>镜像运行失败了。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker run -p 8080:8080 --name helloapp hello-app:latest<br></code></pre></td></tr></table></figure>

<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs n1ql">[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker run -p 8080:8080 --name helloapp hello-app:latest<br>docker: Error response from daemon: failed to <span class="hljs-keyword">create</span> task <span class="hljs-keyword">for</span> container: failed <span class="hljs-keyword">to</span> <span class="hljs-keyword">create</span> shim task: OCI runtime <span class="hljs-keyword">create</span> failed: runc <span class="hljs-keyword">create</span> failed: unable <span class="hljs-keyword">to</span> <span class="hljs-keyword">start</span> container process: exec: <span class="hljs-string">&quot;java&quot;</span>: executable file <span class="hljs-keyword">not</span> found <span class="hljs-keyword">in</span> $<span class="hljs-keyword">PATH</span>: <span class="hljs-keyword">unknown</span>.<br></code></pre></td></tr></table></figure>

<p>缺少 Java 环境。</p>
<p>停止容器，删除容器。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]<span class="hljs-comment"># docker ps -a</span><br>CONTAINER ID   IMAGE              COMMAND                CREATED          STATUS    PORTS                                       NAMES<br>eefe17b7f1e2   hello-app          <span class="hljs-string">&quot;java -jar /app.jar&quot;</span>   2 minutes ago    Created   8080/tcp                                    heuristic_jackson<br>da15a61a2596   hello-app:latest   <span class="hljs-string">&quot;java -jar /app.jar&quot;</span>   12 minutes ago   Created   0.0.0.0:8080-&gt;8080/tcp, :::8080-&gt;8080/tcp   helloapp<br></code></pre></td></tr></table></figure>

<figure class="highlight autoit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs autoit">[root<span class="hljs-symbol">@iZ2ze4hnl6pls28qt4w1ttZ</span> serInfo]<span class="hljs-meta"># docker remove eefe17b7f1e2</span><br>eefe17b7f1e2<br></code></pre></td></tr></table></figure>

<p>删除镜像。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]<span class="hljs-comment"># docker rmi 19baea50ee10</span><br>Untagged: hello-app:latest<br></code></pre></td></tr></table></figure>

<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">[root@iZ2ze4hnl6pls28qt4w1ttZ ser<span class="hljs-literal">Inf</span>o]<span class="hljs-comment"># docker images</span><br>REPOSITORY    <span class="hljs-keyword">TAG</span>       <span class="hljs-title">IMAGE</span> ID       CREATED       SIZE<br>hello-world   latest    feb5d9fea6a5   <span class="hljs-number">3</span> years ago   <span class="hljs-number">13.3</span>kB<br></code></pre></td></tr></table></figure>

<p>重新构建镜像。</p>
<figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile"><span class="hljs-comment"># 基础镜像</span><br><span class="hljs-keyword">FROM</span> scratch<br><span class="hljs-comment"># 作者信息</span><br><span class="hljs-keyword">MAINTAINER</span>  memory<br><span class="hljs-comment"># 安装jdk</span><br><span class="hljs-keyword">RUN</span><span class="language-bash"> apt-get update &amp;&amp; apt-get install -y openjdk-8-jdk</span><br><span class="hljs-comment"># 复制主机jar包至镜像内，复制的目录需放置在 Dockerfile 文件同级目录下</span><br><span class="hljs-keyword">ADD</span><span class="language-bash"> hello-0.0.1-SNAPSHOT.jar app.jar</span><br><span class="hljs-comment"># 容器启动执行命令</span><br><span class="hljs-keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="hljs-string">&quot;java&quot;</span>,<span class="hljs-string">&quot;-jar&quot;</span>, <span class="hljs-string">&quot;/app.jar&quot;</span>]</span><br><span class="hljs-comment"># 对外暴露的端口号</span><br><span class="hljs-keyword">EXPOSE</span>  <span class="hljs-number">8080</span><br></code></pre></td></tr></table></figure>

<p>很显然这条命令又报错了。</p>
<figure class="highlight asciidoc"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs asciidoc">[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker build -t hello-app .<br>[+] Building 0.3s (4/5)<br><span class="hljs-code"> &gt; [1/2] RUN apt-get update &amp;&amp; apt-get install -y openjdk-8-jdk:</span><br><span class="hljs-section">0.215 runc run failed: unable to start container process: exec: &quot;/bin/sh&quot;: stat /bin/sh: no such file or directory</span><br><span class="hljs-section">------</span><br><span class="hljs-section">Dockerfile:6</span><br><span class="hljs-section">--------------------</span><br><span class="hljs-code">   4 |     MAINTAINER  memory</span><br><span class="hljs-code">   5 |     # 安装jdk</span><br><span class="hljs-code">   6 | &gt;&gt;&gt; RUN apt-get update &amp;&amp; apt-get install -y openjdk-8-jdk</span><br><span class="hljs-code">   7 |     # 复制主机jar包至镜像内，复制的目录需放置在 Dockerfile 文件同级目录下</span><br><span class="hljs-section">   8 |     ADD hello-0.0.1-SNAPSHOT.jar app.jar</span><br><span class="hljs-section">--------------------</span><br>ERROR: failed to solve: process &quot;/bin/sh -c apt-get update &amp;&amp; apt-get install -y openjdk-8-jdk&quot; did not complete successfully: exit code: 1<br><br></code></pre></td></tr></table></figure>

<p>修改 Dockerfile 文件。</p>
<figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile"><span class="hljs-comment"># 使用 CentOS 基础镜像</span><br><span class="hljs-keyword">FROM</span> centos:latest<br><span class="hljs-comment"># 作者信息</span><br><span class="hljs-keyword">MAINTAINER</span>  memory<br><span class="hljs-comment"># 安装必要的软件包</span><br><span class="hljs-keyword">RUN</span><span class="language-bash"> yum install -y java-1.8.0-openjdk-devel</span><br><span class="hljs-comment"># 设置工作目录</span><br><span class="hljs-keyword">WORKDIR</span><span class="language-bash"> /app</span><br><span class="hljs-comment"># 复制 JAR 文件到工作目录</span><br><span class="hljs-keyword">COPY</span><span class="language-bash"> hello-0.0.1-SNAPSHOT.jar app.jar</span><br><span class="hljs-comment"># 容器启动执行命令</span><br><span class="hljs-keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="hljs-string">&quot;java&quot;</span>, <span class="hljs-string">&quot;-jar&quot;</span>, <span class="hljs-string">&quot;app.jar&quot;</span>]</span><br><span class="hljs-comment"># 对外暴露的端口号</span><br><span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">8080</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.51cto.com/u_16213457/13009383">dockerfile 安装 java 环境_mob64ca12f66e6c 的技术博客_51CTO 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.51cto.com/u_16213353/12311905">docker 容器配置 java 环境_mob64ca12dd8bce 的技术博客_51CTO 博客</a></p>
<p>又忙活了一个多小时许可证后台管理系统，只要着手搞这玩意儿时间就过得可快了，这会儿都快五点钟，该下班了。</p>
<p>再试试：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 使用 CentOS 基础镜像</span><br>FROM centos:latest<br>FROM openjdk:8-jdk-alpine<br><span class="hljs-comment"># 作者信息</span><br>MAINTAINER  memory<br><span class="hljs-comment"># 配置java环境变量</span><br>ENV JAVA_HOME /opt/jdk/jdk1.8.0_412<br>ENV CLASSPATH <span class="hljs-variable">$JAVA_HOME</span>/lib/dt.jar:<span class="hljs-variable">$JAVA_HOME</span>/lib/tools.jar<br>ENV PATH <span class="hljs-variable">$PATH</span>:<span class="hljs-variable">$JAVA_HOME</span>/bin<br><span class="hljs-comment"># 设置工作目录</span><br>WORKDIR /app<br><span class="hljs-comment"># 复制 JAR 文件到工作目录</span><br>COPY hello-0.0.1-SNAPSHOT.jar app.jar<br><span class="hljs-comment"># 容器启动执行命令</span><br><span class="hljs-comment">#ENTRYPOINT [&quot;java&quot;, &quot;-jar&quot;, &quot;app.jar&quot;]</span><br><span class="hljs-comment"># 对外暴露的端口号</span><br>EXPOSE 8080<br></code></pre></td></tr></table></figure>

<p>待解决问题：</p>
<figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs livecodeserver">unable <span class="hljs-built_in">to</span> <span class="hljs-built_in">start</span> container <span class="hljs-built_in">process</span>: exec: <span class="hljs-string">&quot;java&quot;</span>: executable <span class="hljs-built_in">file</span> <span class="hljs-keyword">not</span> found <span class="hljs-keyword">in</span> $PATH: unknown.<br></code></pre></td></tr></table></figure>

<blockquote>
<p>2025 年 2 月 6 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/lnh1998/article/details/131293754">exec failed: unable to start container process: exec: “ip“: executable file not found in $PATH_oci runtime exec failed: exec failed: unable to st-CSDN 博客</a></p>
<p>问题报错：</p>
<figure class="highlight mel"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mel">OCI runtime <span class="hljs-keyword">exec</span> failed: <span class="hljs-keyword">exec</span> failed: unable to start <span class="hljs-keyword">container</span> process: <span class="hljs-keyword">exec</span>: <span class="hljs-string">&quot;ip&quot;</span>: executable <span class="hljs-keyword">file</span> not found <span class="hljs-keyword">in</span> $PATH: unknown<br></code></pre></td></tr></table></figure>

<p>报错原因：因为该容器的镜像时精简版，内部缺少 iproute2 导致无法使用 ip 命令</p>
<p>解决方式：</p>
<p>进入容器</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker <span class="hljs-built_in">exec</span> -it 容器名 /bin/bash<br></code></pre></td></tr></table></figure>

<p>进入后：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 更新apt</span><br>apt-get update<br><br><span class="hljs-comment"># 安装iproute2</span><br>agt install -y iproute2<br><br><span class="hljs-comment"># 安装完以后退出exit</span><br>docker <span class="hljs-built_in">exec</span> -it 容器名 ip addr<br></code></pre></td></tr></table></figure>

<p>这段不太实用，我的问题不在于容器启动后报错，而是容器根本没有启动成功，没法进入一个不在运行过程中的容器。</p>
<p>镜像 Dockerfile 的问题。</p>
<p><a target="_blank" rel="noopener" href="https://blog.huochengrm.cn/ask/13337.html">如何顺利进入 Docker 容器内部？-HCRM 博客 (huochengrm.cn)</a></p>
<blockquote>
<p>2025 年 2 月 10 日</p>
</blockquote>
<p>本地虚拟机 Docker 安装完成，不过还要修改 Docker Hub 阿里云镜像源。</p>
<p><a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/article/1790498">Docker 系列(3) —— 切换 Docker 镜像源-腾讯云开发者社区-腾讯云 (tencent.com)</a></p>
<p>这样的配置方法相比上面所提供的，也许会更加全面一些。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">vi /etc/docker/daemon.json<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs bash">&#123;<br>  <span class="hljs-string">&quot;registry-mirrors&quot;</span>: [<br>    <span class="hljs-string">&quot;https://7bezldxe.mirror.aliyuncs.com/&quot;</span>,<br>    <span class="hljs-string">&quot;https://docker.mirrors.ustc.edu.cn/&quot;</span>,<br>    <span class="hljs-string">&quot;https://hub-mirror.c.163.com&quot;</span>,<br>    <span class="hljs-string">&quot;https://registry.docker-cn.com&quot;</span><br>  ],<br>  <span class="hljs-string">&quot;insecure-registries&quot;</span>: [],<br>  <span class="hljs-string">&quot;debug&quot;</span>: <span class="hljs-literal">false</span>,<br>  <span class="hljs-string">&quot;experimental&quot;</span>: <span class="hljs-literal">false</span>,<br>  <span class="hljs-string">&quot;features&quot;</span>: &#123;<br>    <span class="hljs-string">&quot;buildkit&quot;</span>: <span class="hljs-literal">true</span><br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl start docker.service<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">systemctl status docker.service<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker pull hello-world<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/YUEAwb/article/details/138108576">Docker 基础命令_docker 查看镜像-CSDN 博客</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker info<br></code></pre></td></tr></table></figure>

<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs awk">Registry Mirrors:<br> https:<span class="hljs-regexp">//</span><span class="hljs-number">7</span>bezldxe.mirror.aliyuncs.com/<br></code></pre></td></tr></table></figure>

<p>显然更新配置后再次拉取镜像没有生效，镜像源还是没有修改完成。</p>
<p>明天见吧，我的朋友。</p>
<h3 id="Dockerfile-部署"><a href="#Dockerfile-部署" class="headerlink" title="Dockerfile 部署"></a>Dockerfile 部署</h3><blockquote>
<p>2025 年 2 月 6 日</p>
</blockquote>
<p>启动成功！</p>
<p><img src="http://blog.memory-life.xyz/Snipaste_2025-02-06_09-35-22.png" alt="Snipaste_2025-02-06_09-35-22"></p>
<p>删除容器，删除镜像，重新构建镜像再运行容器。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker ps -a<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker remove helloapp<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker images<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker rmi hello-app<br></code></pre></td></tr></table></figure>

<p>更新 Dockerfile 文件，选择使用官方 JDK 镜像。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 使用 CentOS 基础镜像</span><br>FROM centos:latest<br><span class="hljs-comment"># 使用官方 JDK 镜像</span><br>FROM openjdk:8-jdk-alpine<br><span class="hljs-comment"># 作者信息</span><br>MAINTAINER  memory<br><span class="hljs-comment"># 查看 JAVA 版本</span><br>RUN java -version<br><span class="hljs-comment"># 设置工作目录</span><br>WORKDIR /app<br><span class="hljs-comment"># 复制 JAR 文件到工作目录</span><br>COPY hello-0.0.1-SNAPSHOT.jar app.jar<br><span class="hljs-comment"># 容器启动执行命令</span><br>ENTRYPOINT [<span class="hljs-string">&quot;java&quot;</span>, <span class="hljs-string">&quot;-jar&quot;</span>, <span class="hljs-string">&quot;app.jar&quot;</span>]<br><span class="hljs-comment"># 对外暴露的端口号</span><br>EXPOSE 8080<br></code></pre></td></tr></table></figure>

<p>把 jar 包和编辑完善的 Dockerfile 文件放在同级目录下。</p>
<p>构建镜像。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker build -t hello-app .<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250206095024612.png" alt="image-20250206095024612"></p>
<p>创建并运行容器。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker run -p 8080:8080 --name helloapp hello-app:latest<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/Snipaste_2025-02-06_09-35-22.png" alt="Snipaste_2025-02-06_09-35-22"></p>
<p>可以说这是今年的开门红，初步掌握一门新技术：docker 容器部署。</p>
<p>进入正在运行中的容器并以命令行交互。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker <span class="hljs-built_in">exec</span> -it helloapp /bin/bash<br></code></pre></td></tr></table></figure>

<p>或者：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker <span class="hljs-built_in">exec</span> -it helloapp /bin/sh<br></code></pre></td></tr></table></figure>

<p>列表查看。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">ls</span><br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]<span class="hljs-comment"># docker exec -it helloapp /bin/sh</span><br>/app <span class="hljs-comment"># ll</span><br>/bin/sh: ll: not found<br>/app <span class="hljs-comment"># ls</span><br>app.jar<br></code></pre></td></tr></table></figure>

<p>退出容器。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">exit</span><br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">/app <span class="hljs-comment"># exit</span><br>[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]<span class="hljs-comment">#</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/u013250861/article/details/126924886">shell：bash【Bourne-Again SHell】_bourne again shell-CSDN 博客</a></p>
<p>[<a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_34326179/article/details/93089023">Linux] Bourne Again Shell-CSDN 博客</a></p>
<p>正巧看到这篇文章，写得很全很详细，点开主页一看竟然是一位年均输出大几百篇技术文章的大佬，不过一九年停更了。</p>
<p>快到饭点了，接下来安排的任务是尝试 docker 部署后台管理项目，以及 docker 远程部署。</p>
<p>同样的步骤，编写 Dockerfile 文件，构建镜像文件，启动并运行容器，接下来就应该开放阿里云服务器端口号了。</p>
<p>倒是接口文档可以正常访问，不过连接数据库失败了。</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">http:<span class="hljs-regexp">//</span><span class="hljs-number">8.141</span>.<span class="hljs-number">90.145</span>:<span class="hljs-number">8082</span><span class="hljs-regexp">/backend-server/</span>doc.html<br></code></pre></td></tr></table></figure>

<p>获取 docker 容器环境变量。</p>
<p>着手测试。</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">http:<span class="hljs-regexp">//</span>localhost:<span class="hljs-number">8080</span><span class="hljs-regexp">/api/</span>test<br></code></pre></td></tr></table></figure>

<p>携带环境变量，启动项目。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">docker run -p 8080:8080 --name helloapp -e APP_NAME=<span class="hljs-string">&quot;My Awesome App&quot;</span> -e APP_PORT=8080 hello-app:latest<br></code></pre></td></tr></table></figure>

<p>可以这么干，那就更新下接口。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 测试接口</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@GetMapping(&quot;/test&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">test</span><span class="hljs-params">()</span> &#123;<br>    System.out.println(<span class="hljs-string">&quot;Hello World&quot;</span>);<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;Hello World&quot;</span>;<br>&#125;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 测试接口2</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@GetMapping(&quot;/test2&quot;)</span><br><span class="hljs-keyword">public</span> String <span class="hljs-title function_">test2</span><span class="hljs-params">()</span> &#123;<br>    Map&lt;String, String&gt; getenv = System.getenv();<br>    System.out.println(getenv);<br>    <span class="hljs-type">String</span> <span class="hljs-variable">appName</span> <span class="hljs-operator">=</span> System.getenv(<span class="hljs-string">&quot;APP_NAME&quot;</span>);<br>    System.out.println(appName);<br>    <span class="hljs-type">String</span> <span class="hljs-variable">appPort</span> <span class="hljs-operator">=</span> System.getenv(<span class="hljs-string">&quot;APP_PORT&quot;</span>);<br>    System.out.println(appPort);<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;Hello World&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>出问题了。</p>
<p>怎么访问不到接口呢。</p>
<p>本地测试没问题啊，docker 部署服务启动也是没问题的，难道是打包更新后的代码出问题了吗，再试试。</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">http:<span class="hljs-regexp">//</span><span class="hljs-number">8.141</span>.<span class="hljs-number">90.145</span>:<span class="hljs-number">8080</span><span class="hljs-regexp">/api/</span>test2<br></code></pre></td></tr></table></figure>

<p>果然是这样，成功了。</p>
<p><img src="http://blog.memory-life.xyz/image-20250206153451255.png" alt="image-20250206153451255"></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]<span class="hljs-comment"># docker run -p 8080:8080 --name helloapp -e APP_NAME=&quot;My Awesome App&quot; -e APP_PORT=8080 hello-app:latest</span><br><br>  .   ____          _            __ _ _<br> /\\ / ___<span class="hljs-string">&#x27;_ __ _ _(_)_ __  __ _ \ \ \ \</span><br><span class="hljs-string">( ( )\___ | &#x27;</span>_ | <span class="hljs-string">&#x27;_| | &#x27;</span>_ \/ _` | \ \ \ \<br> \\/  ___)| |_)| | | | | || (_| |  ) ) ) )<br>  <span class="hljs-string">&#x27;  |____| .__|_| |_|_| |_\__, | / / / /</span><br><span class="hljs-string"> =========|_|==============|___/=/_/_/_/</span><br><span class="hljs-string"> :: Spring Boot ::                (v2.7.7)</span><br><span class="hljs-string"></span><br><span class="hljs-string">2025-02-06 07:30:58.477  INFO 1 --- [           main] org.tellhow.info.hello.HelloApplication  : Starting HelloApplication v0.0.1-SNAPSHOT using Java 1.8.0_212 on 9ed306a10b37 with PID 1 (/app/app.jar started by root in /app)</span><br><span class="hljs-string">2025-02-06 07:30:58.484  INFO 1 --- [           main] org.tellhow.info.hello.HelloApplication  : The following 1 profile is active: &quot;dev&quot;</span><br><span class="hljs-string">2025-02-06 07:30:59.972  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)</span><br><span class="hljs-string">2025-02-06 07:30:59.988  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]</span><br><span class="hljs-string">2025-02-06 07:30:59.988  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.70]</span><br><span class="hljs-string">2025-02-06 07:31:00.135  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext</span><br><span class="hljs-string">2025-02-06 07:31:00.135  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1499 ms</span><br><span class="hljs-string">2025-02-06 07:31:00.679  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path &#x27;</span><span class="hljs-string">&#x27;</span><br><span class="hljs-string">2025-02-06 07:31:00.694  INFO 1 --- [           main] org.tellhow.info.hello.HelloApplication  : Started HelloApplication in 2.989 seconds (JVM running for 3.58)</span><br><span class="hljs-string">Hello world!</span><br><span class="hljs-string">2025-02-06 07:31:06.094  INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet &#x27;</span>dispatcherServlet<span class="hljs-string">&#x27;</span><br><span class="hljs-string">2025-02-06 07:31:06.095  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet &#x27;</span>dispatcherServlet<span class="hljs-string">&#x27;</span><br><span class="hljs-string">2025-02-06 07:31:06.096  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms</span><br><span class="hljs-string">Hello World</span><br><span class="hljs-string">&#123;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin, HOSTNAME=9ed306a10b37, JAVA_ALPINE_VERSION=8.212.04-r0, LD_LIBRARY_PATH=/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64:/usr/lib/jvm/java-1.8-openjdk/jre/../lib/amd64, JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk, APP_NAME=My Awesome App, JAVA_VERSION=8u212, LANG=C.UTF-8, APP_PORT=8080, HOME=/root&#125;</span><br><span class="hljs-string">My Awesome App</span><br><span class="hljs-string">8080</span><br></code></pre></td></tr></table></figure>

<p>嘿嘿哈哈，看来通过 Java 代码获取封装在 Docker 容器环境变量中的服务器硬件信息是可取的，开启下一步修改。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java">Map&lt;String, String&gt; getenv = System.getenv();<br>System.out.println(getenv);<br><span class="hljs-type">String</span> <span class="hljs-variable">appName</span> <span class="hljs-operator">=</span> System.getenv(<span class="hljs-string">&quot;APP_NAME&quot;</span>);<br>System.out.println(appName);<br><span class="hljs-type">String</span> <span class="hljs-variable">appPort</span> <span class="hljs-operator">=</span> System.getenv(<span class="hljs-string">&quot;APP_PORT&quot;</span>);<br>System.out.println(appPort);<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs JAVA"><span class="hljs-comment">// 获取现场服务器硬件信息</span><br>           <span class="hljs-comment">// 获取容器环境变量</span><br>           <span class="hljs-type">LicenseCheckModel</span> <span class="hljs-variable">hardwareInfo</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">LicenseCheckModel</span>();<br>           <span class="hljs-type">String</span> <span class="hljs-variable">ipAddressEnv</span> <span class="hljs-operator">=</span> System.getenv(LicenseConstant.IP_ADDRESS_ENV);<br>           <span class="hljs-type">String</span> <span class="hljs-variable">MacAddressEnv</span> <span class="hljs-operator">=</span> System.getenv(LicenseConstant.MAC_ADDRESS_ENV);<br>           <span class="hljs-type">String</span> <span class="hljs-variable">CpuSerialEnv</span> <span class="hljs-operator">=</span> System.getenv(LicenseConstant.CPU_SERIAL_ENV);<br>           <span class="hljs-type">String</span> <span class="hljs-variable">MainBoardSerialEnv</span> <span class="hljs-operator">=</span> System.getenv(LicenseConstant.MAINBOARD_SERIAL_ENV);<br>           <span class="hljs-keyword">if</span> (ObjectUtils.isNotEmpty(ipAddressEnv)) &#123;<br>               hardwareInfo.setIpAddress(Lists.newArrayList(ipAddressEnv.split(<span class="hljs-string">&quot;,&quot;</span>)));<br>           &#125;<br>           <span class="hljs-keyword">if</span> (ObjectUtils.isNotEmpty(MacAddressEnv)) &#123;<br>               hardwareInfo.setMacAddress(Lists.newArrayList(MacAddressEnv.split(<span class="hljs-string">&quot;,&quot;</span>)));<br>           &#125;<br>           <span class="hljs-keyword">if</span> (ObjectUtils.isNotEmpty(CpuSerialEnv)) &#123;<br>               hardwareInfo.setCpuSerial(CpuSerialEnv);<br>           &#125;<br>           <span class="hljs-keyword">if</span> (ObjectUtils.isNotEmpty(MainBoardSerialEnv)) &#123;<br>               hardwareInfo.setMainBoardSerial(MainBoardSerialEnv);<br>           &#125;<br>           <span class="hljs-comment">// 现场服务器硬件信息</span><br>           <span class="hljs-keyword">if</span> (ObjectUtils.isEmpty(hardwareInfo)) &#123;<br>               log.error(<span class="hljs-string">&quot;请输入现场服务器硬件信息！&quot;</span>);<br>               <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CommonException</span>(<span class="hljs-number">401</span>, <span class="hljs-string">&quot;请输入现场服务器硬件信息！&quot;</span>);<br>           &#125;<br>           <span class="hljs-comment">// 设置现场服务器硬件信息</span><br>           HardwareInfoContext.setHardwareInfo(hardwareInfo);<br></code></pre></td></tr></table></figure>

<p>接下来的内容，就记录在别的栏目了，纯业务，与技术无关。</p>
<blockquote>
<p>2025 年 2 月 7 日</p>
</blockquote>
<p>docker 远程部署。</p>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1776245631845789697#heading-4">IDEA+Docker 远程部署 Sprin - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250207150825887.png" alt="image-20250207150825887"></p>
<p>两天了，刚刚看到这个连接 Docker 失败的提示。</p>
<p>算了，前天的记录内容就网上翻找吧，在此就不做复杂的排版了。</p>
<figure class="highlight mercury"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mercury">Only key-pair ssh auth <span class="hljs-keyword">type</span> <span class="hljs-keyword">is</span> supported for docker connections.<br></code></pre></td></tr></table></figure>

<p>远程部署成功！</p>
<p><img src="http://blog.memory-life.xyz/image-20250207155252693.png" alt="image-20250207155252693"></p>
<blockquote>
<p>2025 年 2 月 8 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1776245631845789697#heading-2">IDEA+Docker 远程部署 Sprin - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/cnds123321/article/details/121947896">在 IDEA 中通过密钥认证的方式使用 SSH 连接远程 Linux 服务器_idea ssh 密码登录-CSDN 博客</a></p>
<h2 id="SSH"><a href="#SSH" class="headerlink" title="SSH"></a>SSH</h2><blockquote>
<p>2025 年 2 月 8 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://worktile.com/kb/ask/1411570.html">openssh 是什么服务器 • Worktile 社区</a></p>
<p>远程连接服务器，除了账号密码还可以使用 ssh 连接。</p>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1776245631845789697#heading-2">IDEA+Docker 远程部署 Spring - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/cnds123321/article/details/121947896">在 IDEA 中通过密钥认证的方式使用 SSH 连接远程 Linux 服务器_idea ssh 密码登录-CSDN 博客</a></p>
<p>在 IDEA 中通过密钥认证的方式使用 SSH 连接远程 Linux 服务器。</p>
<p>昨天使用 Key Pair OpenSSH 连接方式实现 Docker 远程部署，是因为 Docker 远程部署仅支持 Key Pair OpenSSH 连接方式。</p>
<p>然而连接其实是失败了，远程部署显然不应该成功的，还是使用账号密码验证成功，只是来 IDEA 配置中勾选连接方式为 ssh 方式即可。</p>
<p><strong>在 windows 上生成公钥证书。</strong></p>
<ul>
<li>第一步，执行<code>Win+R</code>命令输入<code>cmd</code>打开 DOS 命令行窗口。</li>
<li>第二步，在命令行窗口中输入<code>ssh -V</code>查看 ssh 版本号，判断 ssh 是否可以用，因为我们需要通过<code>ssh</code>来生成证书文件。</li>
<li>第三步，<code>ssh</code>命令可用的话，就继续在命令行窗口输入<code>ssh-keygen -t rsa</code>生成公钥证书和私钥证书文件。生成的目录也指明了，通常在用户的<code>.ssh</code>目录下，其中<code>id_rsa</code>是私钥证书文件，<code>id_rsa.pub</code>为公钥证书文件。</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">win + R<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">ssh -V<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">ssh-keygen -t rsa<br></code></pre></td></tr></table></figure>

<p><strong>将公钥证书放到 Linux 服务器上。</strong></p>
<ul>
<li>第一步，复制 Windows 系统下<code>.ssh</code>目录下生成的公钥证书文件<code>id_rsa.pub</code>的内容。</li>
<li>第二步，在 Linux 系统的/root/.ssh 目录下执行 vi authorized_keys 命令创建一个名为 authorized_keys 的文件，然后将第一步复制的 id_rsa.pub 的内容粘贴到该文件内。这样远程 Linux 服务器就信任本地的 Windows 系统服务器了，你可以在本地的 Windows 系统上通过 ssh 远程登录 Linux 系统了。</li>
<li>第三步，测试。在本地 Windows 系统上输入<code>ssh 用户名@IP地址</code>进行远程登录。如果能登录成功并且能执行 Linux 命令表示配置成功。</li>
</ul>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">ssh</span>-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC9p7KkIDVnVn9XOi4J6qNkwEJ0iVKqMR5gNxW5o1Qhf++ufpzcgro9eDTLkfLA7i9v3oqB6IUzmzF3lKXEnGEcEz+d60QdSUoJFV2+<span class="hljs-number">8</span>kGeCyAfYlSh5hL/DJ79zjwfkWnFqDmAUvznqaYSRxWGLGW3q/<span class="hljs-number">7</span>a09EaAuJ2rmI2Arz76DV1Knr7mu1HLmm6TUuHX7cHdnez8azIxhfm/<span class="hljs-number">0</span>p4OGK9eulK4YGbn1XCqN8oLJfT+MqYx23rpFZBPtd3sjWaxyIqbpzH7r0cfT3tIhO6URyv3kP4YscVccbf4ImP4aJiOjfyGD+JB7hpuhXC3HtH8mhZsOCuDwwkPyi43J7Eew1yXVnPpHIpYXhtryNOEgJfzcbP3QrqnTynrNKiNZQjfo47JBUWFFeWUbEFcJDshKIYOAZb0G9twqbX3ZraVKVAYYd6kKj5a5sge8Ck+CrPXYFgCm3mWkS3W+wPrTOHgqmuKH4gksZT4Zpc1rTmjOLNlRaOggBW8AMvvovteRdF37s= Lenovo@LAPTOP-<span class="hljs-number">5</span>U3S75BI<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">vi authorized_keys<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">ssh 用户名@IP地址<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">C:\WINDOWS\system32&gt;ssh root@8.141.90.145<br>Last login: Sat Feb  8 16:39:45 2025 from 218.94.31.98<br><br>Welcome to Alibaba Cloud Elastic Compute Service !<br>[root@iZ2ze4hnl6pls28qt4w1ttZ ~]<span class="hljs-comment">#</span><br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250208164045006.png" alt="image-20250208164045006"></p>
<p>注意：</p>
<ul>
<li><p>其实就是将本地 Windows 系统上的公钥证书文件 id_rsa.pub 文件上传到远程 Linux 系统上的/root/.ssh 目录下并且重命名为 authorized_keys。</p>
</li>
<li><p>如果已经存在 authorized_keys 文件了，那么直接将复制的内容添加到文件的最后一行。因为每一行都表示一条信任连接，不要去删除。</p>
</li>
</ul>
<p><strong>IDEA 通过 SSH 连接远程 Linux 服务器。</strong></p>
<ul>
<li>第一步，打开<code>File</code>，然后选择<code>Settings...</code></li>
<li>第二步，选择<code>Tools</code>下的<code>SSH Configurations</code>面板，点击<code>+</code>号选择新建 SSH 连接。</li>
<li>第三步，输入连接参数。Host 输入远程 Linux 服务器的 IP 地址；Port 输入端口号，默认是 22；User name 输入登录的用户名；Authentication type 选择 Key pair 表示通过密钥进行验证；Private key file 则选择 Windows 系统下私钥证书 id_rsa 的目录，即在用户目录下的<code>.ssh</code>子目录中；Passphrase 不用填。</li>
<li>第四步，如果有多个连接，那么在<code>SSH Terminal</code>面板中的<code>SSH configuration</code>选择框中选择一台默认连接，或者选择<code>Select SSH configuration on every run</code>表示在每次打开时手动选择要连接的主机。</li>
<li>第五步，在菜单条上的<code>Tools</code>中选择<code>Start SSH Session...</code>开启会话。在出现的<code>Select Host to Connect</code>面板中选择要连接的服务器。</li>
<li>第六步，连接成功！</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">Last login: Sat Feb  8 16:41:19 2025 from 218.94.31.98<br><br>Welcome to Alibaba Cloud Elastic Compute Service !<br>[root@iZ2ze4hnl6pls28qt4w1ttZ ~]<span class="hljs-comment">#</span><br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250208165259585.png" alt="image-20250208165259585"></p>
<p><strong>其他：安装 Open SSH。</strong></p>
<p><a target="_blank" rel="noopener" href="https://worktile.com/kb/ask/1411570.html">openssh 是什么服务器 • Worktile 社区</a></p>
<p><a target="_blank" rel="noopener" href="https://learn.microsoft.com/zh-cn/windows-server/administration/openssh/openssh_install_firstuse?tabs=gui&pivots=windows-server-2019">适用于 Windows 的 OpenSSH 入门 | Microsoft Learn</a></p>
<p>尝试使用刚新学会的三板斧实现 th-iois-file-server 项目远程部署，很显然失败了。</p>
<figure class="highlight smali"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs smali">Can<span class="hljs-built_in"> not </span>construct<span class="hljs-built_in"> instance </span>of com.spotify.docker.client.messages.RegistryAuth: no String-argument<span class="hljs-keyword"> constructor</span>/factory method to deserialize from String value (&#x27;desktop&#x27;)<br> at [Source: N/A; line: -1, column: -1] (through reference chain: java.util.LinkedHashMap[<span class="hljs-string">&quot;credsStore&quot;</span>])<br></code></pre></td></tr></table></figure>

<p>下周见，我的朋友，今天辛苦了。</p>
<h2 id="MinIO"><a href="#MinIO" class="headerlink" title="MinIO"></a>MinIO</h2><blockquote>
<p>2025 年 4 月 26 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.minio.org.cn/overview.shtml">MinIO | 企业级、高性能对象存储</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250426163420399.png" alt="image-20250426163420399"></p>
<p>他奶奶的，本地虚拟机又启动不了了。</p>
<p><img src="http://blog.memory-life.xyz/image-20250426164425964.png" alt="image-20250426164425964"></p>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1811341197480361986">MinIO 对象存储(可以当作图床免费) - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">admin</span>, <span class="hljs-number">12345678</span><br></code></pre></td></tr></table></figure>

<blockquote>
<p>2025 年 1 月 15 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7443658338867134518">这年头不会还有谁没碰过 minio 的吧？这可太…🤡 文件存储那些“坑”，你踩过几个？想象一下，你正在开发一个新项目，老 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1772506865981321218">MinIO+Docker 从零搭建一个文件 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1811341197480361986">MinIO 对象存储(可以当作图床免费) - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/post/1725379904230518786#heading-0">Springboot 整合 Minio 全流程 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/article/1701451">centos7 安装 Docker 详细步骤（无坑版教程）-腾讯云开发者社区-腾讯云 (tencent.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7203258813893345340">Docker 搭建 Minio 对象存储服务 MinIO MinIO 是一款基于 Go 语言发开的高性能、分布式的对象存储 - 掘金 (juejin.cn)</a></p>
<h2 id="虚拟机"><a href="#虚拟机" class="headerlink" title="虚拟机"></a>虚拟机</h2><blockquote>
<p>2025 年 1 月 13 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/article/2132823">ubuntu 与 centos 的对比和选择「建议收藏」-腾讯云开发者社区-腾讯云 (tencent.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/kinggaiwusi/article/details/71081785">CentOS、Ubuntu、Debian 三个 linux 比较异同_debian 和 ubuntu 的区别-CSDN 博客</a></p>
<p>虚拟机。</p>
<p>在虚拟机上进行的最多的操作便是部署项目，以及间歇性熟悉基本的 Linux 命令。</p>
<p>最近需要抽出时间来巩固下 Linux 基本操作命令，学习如何编写脚本来获取 Linux 服务器硬件信息。</p>
<blockquote>
<p>2025 年 1 月 14 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/WXD121110/article/details/134796160">Linux 获取电脑硬件信息_linux 获取计算机信息-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/article/1824974">9 个 Linux 常用查看系统硬件信息命令(实例详解)-腾讯云开发者社区-腾讯云 (tencent.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.51cto.com/u_16099240/9674953">如何制作 centos 安装光盘 centos 光盘映像文件怎么安装_mob6454cc6c1f4a 的技术博客_51CTO 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://mirrors.aliyun.com/centos/">centos 安装包下载_开源镜像站-阿里云 (aliyun.com)</a></p>
<p>Linux 脚本。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-meta">#!/bin/bash</span><br><br>OUTPUT_FILE=<span class="hljs-string">&quot;<span class="hljs-variable">$HOME</span>/Desktop/OutputFile.txt&quot;</span><br><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;开始获取本机信息...&quot;</span><br><br><span class="hljs-comment"># 清空或创建输出文件</span><br>&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br><br><span class="hljs-comment"># 获取本机IP地址</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;本机IP地址：&quot;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br>ip addr show | grep -Eo <span class="hljs-string">&#x27;inet ([0-9]&#123;1,3&#125;\.)&#123;3&#125;[0-9]&#123;1,3&#125;/[0-9]&#123;1,2&#125;&#x27;</span> | grep -Eo <span class="hljs-string">&#x27;([0-9]&#123;1,3&#125;\.)&#123;3&#125;[0-9]&#123;1,3&#125;&#x27;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;&quot;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br><br><span class="hljs-comment"># 获取本机MAC地址</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;本机MAC地址：&quot;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br>ip <span class="hljs-built_in">link</span> show | grep -Eo <span class="hljs-string">&#x27;(([0-9a-fA-F]&#123;2&#125;:)&#123;5&#125;[0-9a-fA-F]&#123;2&#125;)&#x27;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;&quot;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br><br><span class="hljs-comment"># 获取本机CPU序列号（注意：Linux系统通常没有CPU序列号的概念，这里用CPU型号代替）</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;CPU型号：&quot;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br>lscpu | grep -E <span class="hljs-string">&#x27;Model name|CPU(s):&#x27;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;&quot;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br><br><span class="hljs-comment"># 获取本机主板序列号</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;主板序列号：&quot;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br>sudo dmidecode -s baseboard-serial-number &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span> 2&gt;/dev/null<br><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;本机信息获取完成，结果已保存到 <span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br><br><span class="hljs-comment"># 暂停，以便用户查看输出文件（在终端中按任意键继续）</span><br><span class="hljs-built_in">read</span> -p <span class="hljs-string">&quot;按任意键退出...&quot;</span> dummy<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs bash">本机IP地址：<br>127.0.0.1<br>192.168.118.16<br>192.168.122.1<br>172.30.0.1<br>172.18.0.1<br>172.17.0.1<br><br>本机MAC地址：<br>00:00:00:00:00:00<br>00:00:00:00:00:00<br>54:14:a7:16:a5:e7<br>ff:ff:ff:ff:ff:ff<br>52:54:00:55:4a:6c<br>ff:ff:ff:ff:ff:ff<br>52:54:00:55:4a:6c<br>ff:ff:ff:ff:ff:ff<br>02:42:21:c3:65:a2<br><br>CPU型号：<br><br>主板序列号：<br>/66VXC73/CNPE10009806QG/<br></code></pre></td></tr></table></figure>

<p>本机 CPU 序列号：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 获取本机CPU序列号（注意：Linux系统通常没有CPU序列号的概念，这里用CPU型号代替）</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;CPU型号：&quot;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br>lscpu | grep -E <span class="hljs-string">&#x27;Model name|CPU(s):&#x27;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;&quot;</span> &gt;&gt; <span class="hljs-string">&quot;<span class="hljs-variable">$OUTPUT_FILE</span>&quot;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">lscpu<br></code></pre></td></tr></table></figure>

<blockquote>
<p>2025 年 1 月 17 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_37841024/article/details/136596187">WSL 是什么？和虚拟机有什么区别_wsl 和虚拟机区别-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://mbd.baidu.com/newspage/data/dtlandingsuper?nid=dt_5296754215317966944&sourceFrom=search_a">WSL 和虚拟机，哪个更适合你 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://huaweicloud.csdn.net/6707b79be2ce0119e0a1fdb3.html">WSL 和虚拟机的区别是什么？<em>linux</em>我想要身体健康-华为开发者空间 (csdn.net)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/crazywkl/article/details/142317641">手把手教你如何安装使用，适用于 Linux 的 Windows 子系统 WSL_wsl 安装-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/zhangzl419/p/16149396.html">颠覆虚拟机的大神——WSL 来了 - zhangzl419 - 博客园 (cnblogs.com)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250117100141936.png" alt="image-20250117100141936"></p>
<blockquote>
<p>2025 年 1 月 23 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1792198729983729251&wfr=spider&for=pc">解决虚拟机连不上网的五大技巧：从排查到修复，一篇文章让你彻底 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/lengchun10/article/details/143004212">在线就能用的 linux 环境（练习命令用）_在线 linux 模拟环境-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_45957158/article/details/141424841">VMware 虚拟机无法联网 ping 不通_vmware 虚拟机网络连接不上-CSDN 博客</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250123113444304.png" alt="image-20250123113444304"></p>
<p><a target="_blank" rel="noopener" href="https://www.abackup.com/enterprise-backup/vmware-internet-not-working-666.html">VMware 虚拟机网络连接不上怎么办？帮您逐个排查！ (abackup.com)</a></p>
<p>阿里云。</p>
<p><a target="_blank" rel="noopener" href="https://free.aliyun.com/?spm=5176.12818093_47.0.0.3be916d03XnbJv">阿里云免费试用 - 阿里云 (aliyun.com)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250123115613845.png" alt="image-20250123115613845"></p>
<p><img src="http://blog.memory-life.xyz/image-20250123115858152.png" alt="image-20250123115858152"></p>
<p>连上了，他妈的。</p>
<p><img src="http://blog.memory-life.xyz/image-20250123120205749.png" alt="image-20250123120205749"></p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/yayuya/p/18000907">Linux 系统之安装 java 开发环境 - 爵岚 - 博客园 (cnblogs.com)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250123120857731.png" alt="image-20250123120857731"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title function_">fetchCpuId</span><span class="hljs-params">()</span> &#123;<br>     <span class="hljs-type">String</span> <span class="hljs-variable">cpuId</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;&quot;</span>;<br>     String[] command = &#123;<span class="hljs-string">&quot;/bin/bash&quot;</span>, <span class="hljs-string">&quot;-c&quot;</span>, <span class="hljs-string">&quot;sudo dmidecode -t processor | grep &#x27;ID&#x27; | awk -F &#x27;:&#x27; &#x27;&#123;print $2&#125;&#x27; | head -n 1&quot;</span>&#125;;<br><br>     <span class="hljs-type">ProcessBuilder</span> <span class="hljs-variable">processBuilder</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ProcessBuilder</span>(command);<br>     <span class="hljs-keyword">try</span> &#123;<br>         <span class="hljs-type">Process</span> <span class="hljs-variable">process</span> <span class="hljs-operator">=</span> processBuilder.start();<br>         <span class="hljs-type">BufferedReader</span> <span class="hljs-variable">reader</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BufferedReader</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">InputStreamReader</span>(process.getInputStream()));<br>         String line;<br>         <span class="hljs-keyword">if</span> ((line = reader.readLine()) != <span class="hljs-literal">null</span>) &#123;<br>             cpuId = line.trim();<br>         &#125;<br>         reader.close();<br>         <span class="hljs-type">int</span> <span class="hljs-variable">exitCode</span> <span class="hljs-operator">=</span> process.waitFor();<br>         <span class="hljs-keyword">if</span> (exitCode != <span class="hljs-number">0</span>) &#123;<br>             <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;Command exited with error code: &quot;</span> + exitCode);<br>         &#125;<br>     &#125; <span class="hljs-keyword">catch</span> (IOException | InterruptedException e) &#123;<br>         <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(e);<br>     &#125;<br>     <span class="hljs-keyword">return</span> cpuId;<br> &#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title function_">fetchSerialNumber</span><span class="hljs-params">()</span> &#123;<br>    <span class="hljs-type">String</span> <span class="hljs-variable">serialNumber</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;&quot;</span>;<br>    <span class="hljs-comment">// 构建要执行的命令</span><br>    String[] command = &#123;<span class="hljs-string">&quot;/bin/bash&quot;</span>, <span class="hljs-string">&quot;-c&quot;</span>, <span class="hljs-string">&quot;sudo dmidecode | grep &#x27;Serial Number&#x27; | awk -F &#x27;:&#x27; &#x27;&#123;print $2&#125;&#x27; | head -n 1&quot;</span>&#125;;<br><br>    <span class="hljs-comment">// 创建ProcessBuilder对象</span><br>    <span class="hljs-type">ProcessBuilder</span> <span class="hljs-variable">processBuilder</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ProcessBuilder</span>(command);<br>    <span class="hljs-keyword">try</span> &#123;<br>        <span class="hljs-comment">// 启动进程</span><br>        <span class="hljs-type">Process</span> <span class="hljs-variable">process</span> <span class="hljs-operator">=</span> processBuilder.start();<br>        <span class="hljs-comment">// 读取命令输出</span><br>        <span class="hljs-type">BufferedReader</span> <span class="hljs-variable">reader</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BufferedReader</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">InputStreamReader</span>(process.getInputStream()));<br>        String line;<br>        <span class="hljs-keyword">if</span> ((line = reader.readLine()) != <span class="hljs-literal">null</span>) &#123;<br>            <span class="hljs-comment">// 移除输出中的空白字符</span><br>            serialNumber = line.trim();<br>        &#125;<br>        reader.close();<br>        <span class="hljs-comment">// 等待进程结束并获取退出码</span><br>        <span class="hljs-type">int</span> <span class="hljs-variable">exitCode</span> <span class="hljs-operator">=</span> process.waitFor();<br>        <span class="hljs-keyword">if</span> (exitCode != <span class="hljs-number">0</span>) &#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;Command exited with error code: &quot;</span> + exitCode);<br>        &#125;<br>    &#125; <span class="hljs-keyword">catch</span> (IOException | InterruptedException e) &#123;<br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(e);<br>    &#125;<br>    <span class="hljs-keyword">return</span> serialNumber;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// CPU序列号(或主板序列号)的正则表达式(宽松匹配)</span><br><span class="hljs-comment">// 假设序列号由字母、数字、连字符、点和空格组成，长度在10到40个字符之间</span><br><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">SERIAL_REGEX</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;^[A-Za-z0-9\\-.\\s]&#123;8,40&#125;$&quot;</span>;<br><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">Pattern</span> <span class="hljs-variable">SERIAL_PATTERN</span> <span class="hljs-operator">=</span> Pattern.compile(SERIAL_REGEX);<br></code></pre></td></tr></table></figure>

<blockquote>
<p>2025 年 1 月 25 日</p>
</blockquote>
<p>脚本，命令。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">sudo dmidecode -t processor | grep <span class="hljs-string">&#x27;ID&#x27;</span> | awk -F <span class="hljs-string">&#x27;:&#x27;</span> <span class="hljs-string">&#x27;&#123;print $2&#125;&#x27;</span> | <span class="hljs-built_in">head</span> -n 1<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">sudo dmidecode | grep <span class="hljs-string">&#x27;Serial Number&#x27;</span> | awk -F <span class="hljs-string">&#x27;:&#x27;</span> <span class="hljs-string">&#x27;&#123;print $2&#125;&#x27;</span> | <span class="hljs-built_in">head</span> -n 1<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">ifconfig | grep -Eo <span class="hljs-string">&#x27;inet (addr:)?([0-9]*\.)&#123;3&#125;[0-9]*&#x27;</span> | grep -Eo <span class="hljs-string">&#x27;([0-9]*\.)&#123;3&#125;[0-9]*&#x27;</span> | grep -v <span class="hljs-string">&#x27;127.0.0.1&#x27;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">ip <span class="hljs-built_in">link</span> show | awk <span class="hljs-string">&#x27;/ether/ &#123;match($0, /ether ([0-9a-fA-F:]+)/, arr); print $2, arr[1]&#125;&#x27;</span><br></code></pre></td></tr></table></figure>

<blockquote>
<p>2025 年 2 月 10 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_56175058/article/details/137389933?ops_request_misc=%7B%22request_id%22:%22bfff67e0e3269029991439f935473c9a%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=bfff67e0e3269029991439f935473c9a&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-3-137389933-null-null.142%5Ev101%5Econtrol&utm_term=centos%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B%E8%AF%A6%E8%A7%A3&spm=1018.2226.3001.4187">CentOS 的安装——超详细教程_centos 安装教程详解，面试官不讲武德-CSDN 博客</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250210094759039.png" alt="image-20250210094759039"></p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-attribute">my_CentOS7</span><br>admin<br>admin123<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://baike.baidu.com/item/ISO%E6%96%87%E4%BB%B6/2497244">ISO 文件_百度百科 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/ataoxz/p/18446413">查看虚拟机 centos 7 的 IP 地址和命令 - 数据派 - 博客园 (cnblogs.com)</a></p>
<figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs pf">[admin@localhost ~]$ ip addr<br><span class="hljs-number">1</span>: lo: <span class="hljs-variable">&lt;LOOPBACK,UP,LOWER_UP&gt;</span> mtu <span class="hljs-number">65536</span> qdisc noqueue <span class="hljs-keyword">state</span> UNKNOWN qlen <span class="hljs-number">1</span><br>    link/loopback <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span> brd <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span><br>    <span class="hljs-keyword">inet</span> <span class="hljs-number">127.0</span>.<span class="hljs-number">0.1</span>/<span class="hljs-number">8</span> scope host lo<br>       valid_lft forever preferred_lft forever<br>    <span class="hljs-keyword">inet6</span> ::<span class="hljs-number">1</span>/<span class="hljs-number">128</span> scope host<br>       valid_lft forever preferred_lft forever<br><span class="hljs-number">2</span>: ens32: <span class="hljs-variable">&lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt;</span> mtu <span class="hljs-number">1500</span> qdisc pfifo_fast <span class="hljs-keyword">state</span> DOWN qlen <span class="hljs-number">1000</span><br>    link/ether <span class="hljs-number">00</span>:<span class="hljs-number">0</span>c:<span class="hljs-number">29</span>:d7:<span class="hljs-number">0</span>d:<span class="hljs-number">5</span>c brd ff:ff:ff:ff:ff:ff<br><span class="hljs-number">3</span>: virbr0: <span class="hljs-variable">&lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt;</span> mtu <span class="hljs-number">1500</span> qdisc noqueue <span class="hljs-keyword">state</span> DOWN qlen <span class="hljs-number">1000</span><br>    link/ether <span class="hljs-number">52</span>:<span class="hljs-number">54</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">81</span>:b0 brd ff:ff:ff:ff:ff:ff<br>    <span class="hljs-keyword">inet</span> <span class="hljs-number">192.168</span>.<span class="hljs-number">122.1</span>/<span class="hljs-number">24</span> brd <span class="hljs-number">192.168</span>.<span class="hljs-number">122.255</span> scope <span class="hljs-keyword">global</span> virbr0<br>       valid_lft forever preferred_lft forever<br><span class="hljs-number">4</span>: virbr0-nic: <span class="hljs-variable">&lt;BROADCAST,MULTICAST&gt;</span> mtu <span class="hljs-number">1500</span> qdisc pfifo_fast master virbr0 <span class="hljs-keyword">state</span> DOWN qlen <span class="hljs-number">1000</span><br>    link/ether <span class="hljs-number">52</span>:<span class="hljs-number">54</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">81</span>:b0 brd ff:ff:ff:ff:ff:ff<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">vi /etc/sysconfig/network-scripts/ifcfg-ens33<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/xiaogengtongxu/article/details/138187379">Linux 网络基础_route-ens33-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1749080831704401137&wfr=spider&for=pc">「科普」BIOS 是什么？BIOS 怎么进入，BIOS 里面可以设置什么东西？ (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_73500410/article/details/143318166">Linux 远程连接没有 ens33ip 地址问题解决_linuxens33 没有 ip 地址-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_58743438/article/details/143477390">linux 下修改完配置文件如何保存_linux 修改配置文件怎么保存退出-CSDN 博客</a></p>
<figure class="highlight erlang-repl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs erlang-repl">按w是保存<br>按wq是保存并退出<br>按wq!是强制保存并退出<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_47540149/article/details/136106803">Ubuntu user is not in the sudoers file. This incident will be reported 解决办法-CSDN 博客</a></p>
<p>特么的总算找着解决办法了。</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-attribute">su</span> -<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">vi /etc/sysconfig/network-scripts/ifcfg-ens32<br></code></pre></td></tr></table></figure>

<p>好熟悉的报错：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@localhost ~]<span class="hljs-comment"># systemctl start network.service</span><br>Job <span class="hljs-keyword">for</span> network.service failed because the control process exited with error code. See <span class="hljs-string">&quot;systemctl status network.service&quot;</span> and <span class="hljs-string">&quot;journalctl -xe&quot;</span> <span class="hljs-keyword">for</span> details.<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@localhost ~]<span class="hljs-comment"># journalctl -xe</span><br>-- Subject: Unit network.service has begun start-up<br>-- Defined-By: systemd<br>-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel<br>--<br>-- Unit network.service has begun starting up.<br>Feb 10 03:31:04 localhost.localdomain network[45746]: Bringing up loopback interface:  [  OK  ]<br>Feb 10 03:31:04 localhost.localdomain NetworkManager[743]: &lt;info&gt;  [1739187064.9118] audit: op=<span class="hljs-string">&quot;connection-activate&quot;</span> uuid=<span class="hljs-string">&quot;28</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: Bringing up interface ens32:  Error: Connection activation failed: No s</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: [FAILED]</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain systemd[1]: network.service: control process exited, code=exited status=1</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain systemd[1]: Failed to start LSB: Bring up/down networking.</span><br><span class="hljs-string">-- Subject: Unit network.service has failed</span><br><span class="hljs-string">-- Defined-By: systemd</span><br><span class="hljs-string">-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel</span><br><span class="hljs-string">--</span><br><span class="hljs-string">-- Unit network.service has failed.</span><br><span class="hljs-string">--</span><br><span class="hljs-string">-- The result is failed.</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain systemd[1]: Unit network.service entered failed state.</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain systemd[1]: network.service failed.</span><br><span class="hljs-string">Feb 10 03:31:04 localhost.localdomain polkitd[628]: Unregistered Authentication Agent for unix-process:45740:499336 (system b</span><br><span class="hljs-string">lines 1651-1680/1680 (END)</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/songfeigogogo/p/18395485">Linux：Job for network.service failed because the control process exited with error code - 宋霏 - 博客园 (cnblogs.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_75184408/article/details/143927245">虚拟机重启网卡报错:Job for network.service failed because the control process exited with error code.-CSDN 博客</a></p>
<p>没用。</p>
<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/465361132">虚拟机报错：Job for network.service failed because the control process exited with error code - 知乎 (zhihu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.51cto.com/waxyz/5337188">network.service - LSB: Bring up/down networking Loaded: loaded (/etc/rc.d/init.d/network; bad; v_源知原味的技术博客_51CTO 博客</a></p>
<p>特么十年前的帖子都找来了，没有解决问题。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs">无法连接虚拟设备 ide1:0，因为主机上没有相应的设备。<br>您要在每次开启此虚拟机时都尝试连接此虚拟设备吗?<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/jingjing0920/p/9889887.html">无法连接虚拟设备 ide1:0，因为主机上没有相应的设备。您要在每次开启此虚拟机时都尝试连接此虚拟设备吗? - jingjing0920 - 博客园 (cnblogs.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_46858088/article/details/135277892">无法连接虚拟机设备 ide1：0，因为主机上没有相应的设备。您要每次在开启此虚拟机时都尝试连接此虚拟设备吗？_无法连接虚拟设备 ide1:0,因为主机上没有相应的设备。 您要在每次开启此虚拟机时-CSDN 博客</a></p>
<p>好像跟开启虚拟机时的告警信息也无关，同样解决不了问题。</p>
<p>这个方案挺全，试试看：<a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_46142986/article/details/130702280">Job for network.service failed because the control process exited with error code.-CSDN 博客</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs bash">TYPE=Ethernet<br>PROXY_METHOD=none<br>BROWSER_ONLY=no<br>BOOTPROTO=dhcp<br>DEFROUTE=<span class="hljs-built_in">yes</span><br>HWADDR=00:0c:29:d7:0d:5c<br>IPV4_FAILURE_FATAL=no<br>IPV6INIT=<span class="hljs-built_in">yes</span><br>IPV6_AUTOCONF=<span class="hljs-built_in">yes</span><br>IPV6_DEFROUTE=<span class="hljs-built_in">yes</span><br>IPV6_FAILURE_FATAL=no<br>IPV6_ADDR_GEN_MODE=stable-privacy<br>NAME=ens32<br>UUID=28699bd2-8cc2-41d1-91c2-12de41c04007<br>DEVICE=ens32<br>ONBOOT=<span class="hljs-built_in">yes</span><br></code></pre></td></tr></table></figure>

<p>静态 ip 把 BOOTPROTO 改为 static，重启成功了。</p>
<p>不过 ifconfig 还是 没有 ip 地址，为什么呢。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@localhost ~]<span class="hljs-comment"># ifconfig</span><br>ens32: flags=4099&lt;UP,BROADCAST,MULTICAST&gt;  mtu 1500<br>        inet6 fe80::20c:29ff:fed7:d5c  prefixlen 64  scopeid 0x20&lt;<span class="hljs-built_in">link</span>&gt;<br>        ether 00:0c:29:d7:0d:5c  txqueuelen 1000  (Ethernet)<br>        RX packets 736  bytes 156623 (152.9 KiB)<br>        RX errors 0  dropped 0  overruns 0  frame 0<br>        TX packets 18  bytes 4068 (3.9 KiB)<br>        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0<br></code></pre></td></tr></table></figure>

<p>查看下你电脑有没有禁用了 VMware DHCP service 和 VMware NAT service 这几个 vm 服务，如果禁用则开启。</p>
<p>查看了下果真未开启，尝试开启但失败了。</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_37263429/article/details/138305045">Vmware Linux 虚拟机连不上网怎么办？_虚拟机 linux 无法联网-CSDN 博客</a></p>
<p>我也这么干一遍：先把虚拟机关机，再打开<strong>vmware 首页</strong> ，打开<strong>编辑</strong>， 再打开<strong>虚拟网络编辑器</strong>，选择其中的第一个<strong>VMnet0</strong>，然后点击左下角的<strong>还原默认设置</strong>。</p>
<p>也还是没啥用。</p>
<p>艹，这就成功了，虚拟机连接网络成功，FinalShell 连接本机虚拟机成功，虚拟机网络配置完成。</p>
<p>这么长时间了，总算搞懂了网络配置里的歪门邪道，年前留下的最后一个问题也总算在今天解决，二十天的时间跨度不过如此。</p>
<p>我什么都能解决。</p>
<blockquote>
<p>2025 年 2 月 10 日</p>
</blockquote>
<h3 id="一条龙"><a href="#一条龙" class="headerlink" title="一条龙"></a>一条龙</h3><p>下载光盘映像文件，根据 .iso 文件创建虚拟机，配置虚拟机硬件信息，设置用户名密码，启动。</p>
<p>看这篇就够了：<a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_56175058/article/details/137389933?ops_request_misc=%7B%22request_id%22:%22bfff67e0e3269029991439f935473c9a%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=bfff67e0e3269029991439f935473c9a&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-3-137389933-null-null.142%5Ev101%5Econtrol&utm_term=centos%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B%E8%AF%A6%E8%A7%A3&spm=1018.2226.3001.4187">CentOS 的安装——超详细教程_centos 安装教程详解，面试官不讲武德-CSDN 博客</a></p>
<p>重点来了，从去年开始反复困扰我的本机虚拟机连接网络失败的问题，在这里简要分析下整个网络配置中需要注意的点。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">ifconfig<br></code></pre></td></tr></table></figure>

<p>执行这条命令，虚拟机网卡 ens32 网络连接是有问题的，查看下配置文件。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">vim /etc/sysconfig/network-scripts/ifcfg-ens32<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs bash">TYPE=Ethernet<br>PROXY_METHOD=none<br>BROWSER_ONLY=no<br>BOOTPROTO=dhcp<br>DEFROUTE=<span class="hljs-built_in">yes</span><br>HWADDR=00:0c:29:d7:0d:5c<br>IPV4_FAILURE_FATAL=no<br>IPV6INIT=<span class="hljs-built_in">yes</span><br>IPV6_AUTOCONF=<span class="hljs-built_in">yes</span><br>IPV6_DEFROUTE=<span class="hljs-built_in">yes</span><br>IPV6_FAILURE_FATAL=no<br>IPV6_ADDR_GEN_MODE=stable-privacy<br>NAME=ens32<br>UUID=28699bd2-8cc2-41d1-91c2-12de41c04007<br>DEVICE=ens32<br>ONBOOT=<span class="hljs-built_in">yes</span><br></code></pre></td></tr></table></figure>

<p>ONBOOT=yes，修改配置文件结束后竟然重启网络服务失败了。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">[root@localhost ~]<span class="hljs-comment"># systemctl start network.service</span><br>Job <span class="hljs-keyword">for</span> network.service failed because the control process exited with error code. See <span class="hljs-string">&quot;systemctl status network.service&quot;</span> and <span class="hljs-string">&quot;journalctl -xe&quot;</span> <span class="hljs-keyword">for</span> details.<br></code></pre></td></tr></table></figure>

<p>查了很多资料和方案，贴出来最全的博客文章吧，里面所有的方法都试过了.</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_46142986/article/details/130702280">Job for network.service failed because the control process exited with error code.-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_37263429/article/details/138305045">Vmware Linux 虚拟机连不上网怎么办？_虚拟机 linux 无法联网-CSDN 博客</a></p>
<p>最终我尝试把 BOOTPROTO 改为 static 即静态 IP，虚拟机网络服务竟然重启成功，不过 ifconfig 还是 没有 ip 地址，为啥呢。</p>
<p>因为改成静态 ip 了，配置文件里应该相应要增加这些配置信息才对：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">IPADDR=192.168.1.100							<span class="hljs-comment"># 静态ip地址</span><br>PREFIX=24  <span class="hljs-comment"># 或者使用 NETMASK=255.255.255.0		   # 子网掩码</span><br>GATEWAY=192.168.1.1      						 <span class="hljs-comment"># 网关</span><br></code></pre></td></tr></table></figure>

<p>由于虚拟机未配置动态主机配置协议，那本机即宿主机服务当然不会在运行中，因为 win10 默认：不存在其他服务应用到这俩服务后就自动关闭。</p>
<p><img src="http://blog.memory-life.xyz/image-20250210151057680.png" alt="image-20250210151057680"></p>
<p>那还是把 BOOTPROTO 改回 dhcp 即动态主机配置协议吧，结果重启网络服务仍然成功了，执行 ifconfig 命令后结果完全正常。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash">[admin@localhost ~]$ ifconfig<br>ens32: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;  mtu 1500<br>        inet 192.168.229.128  netmask 255.255.255.0  broadcast 192.168.229.255<br>        inet6 fe80::20c:29ff:fed7:d5c  prefixlen 64  scopeid 0x20&lt;<span class="hljs-built_in">link</span>&gt;<br>        ether 00:0c:29:d7:0d:5c  txqueuelen 1000  (Ethernet)<br>        RX packets 36660  bytes 4378000 (4.1 MiB)<br>        RX errors 0  dropped 0  overruns 0  frame 0<br>        TX packets 55849  bytes 14707128 (14.0 MiB)<br>        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0<br></code></pre></td></tr></table></figure>

<p>这是现在的配置文件内容：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs bash">TYPE=Ethernet<br>PROXY_METHOD=none<br>BROWSER_ONLY=no<br>BOOTPROTO=dhcp<br>DEFROUTE=<span class="hljs-built_in">yes</span><br>HWADDR=00:0c:29:d7:0d:5c<br>IPV4_FAILURE_FATAL=no<br>IPV6INIT=<span class="hljs-built_in">yes</span><br>IPV6_AUTOCONF=<span class="hljs-built_in">yes</span><br>IPV6_DEFROUTE=<span class="hljs-built_in">yes</span><br>IPV6_FAILURE_FATAL=no<br>IPV6_ADDR_GEN_MODE=stable-privacy<br>NAME=ens32<br>UUID=28699bd2-8cc2-41d1-91c2-12de41c04007<br>ONBOOT=<span class="hljs-built_in">yes</span><br></code></pre></td></tr></table></figure>

<p>搞半天花里胡哨的，其实就是把 dhcp 改成 static 又改回 dhcp 罢了， 额外操作根本不需要，不过确实节外生枝学到了不少。</p>
<p>本机虚拟机安装及网络配置完全结束。</p>
<blockquote>
<p>2025 年 2 月 17 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/u014685611/article/details/143641825">filezilla 向虚拟机 Linux 传输文件失败且直接在 Linux 创建文件夹失败的解决方案_550 could get file size-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/Larry2015/article/details/137072507">SSH 客户端连接 Linux 成功，但是传输文件失败_ssh 无法传输文件-CSDN 博客</a></p>
<p>[linux 不能上传文件 - 腾讯云开发者社区 - 腾讯云 (tencent.com)](<a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/information/linux">https://cloud.tencent.com/developer/information/linux</a> 不能上传文件)</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_73756108/article/details/136393506">VM 虚拟机无法传输文件（更新时间 24/3/3）-CSDN 博客</a></p>
<h2 id="内网穿透"><a href="#内网穿透" class="headerlink" title="内网穿透"></a>内网穿透</h2><blockquote>
<p>2025 年 1 月 9 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://zhidao.baidu.com/question/508957260536572364.html?fr=search&word=%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F%E5%B7%A5%E5%85%B7">有哪些简单实用的端口映射(内网穿透)软件工具?_百度知道 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/chucksun0426/article/details/121558231">内网穿透（frp、zerotier）-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://hsk.oray.com/news/36175.html">内网穿透几种方式？怎么搭建内网穿透？-贝锐花生壳官网 (oray.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_23710315/article/details/135334066">内网穿透方案&amp;FRP 内网穿透实战（基础版）-CSDN 博客</a></p>
<h2 id="小程序"><a href="#小程序" class="headerlink" title="小程序"></a>小程序</h2><blockquote>
<p>2025 年 1 月 9 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7376180143376908300">从零开始三天学会微信小程序开发（一）看到不少入门的小程序开发者不断的问重复性的问题，我们从实战角度开发了这个课程，希望能 - 掘金 (juejin.cn)</a></p>
<blockquote>
<p>2025 年 3 月 29 日</p>
</blockquote>
<p>注册微信小程序，下载安装小程序开发工具，创建小程序项目，预览和发布小程序，了解项目目录结构；</p>
<p>删除一个页面，添加一个新的页面，编写第 1 个界面，给页面绑定数据，给页面绑定数组数据。</p>
<p><a target="_blank" rel="noopener" href="https://www.bmobapp.com/app/list">应用列表 - Bmob 后端云 (bmobapp.com)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250329105347905.png" alt="image-20250329105347905"></p>
<p><a target="_blank" rel="noopener" href="https://gitee.com/bmober/hydrogen-js-sdk/tree/master/dist">hydrogen-js-sdk: Bmob 后端云小程序 SDK。 - Gitee.com</a></p>
<p>在页面之间传递参数，获取评语内容，封装一个方法，按钮绑定方法，看调试器，实现复制、分享功能，如何选择主题。</p>
<h2 id="MongoDB"><a href="#MongoDB" class="headerlink" title="MongoDB"></a>MongoDB</h2><blockquote>
<p>2025 年 1 月 15 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7277786940169109567">高效存储，万物皆可 Mongo！SpringBoot+MongoDB 教程，「从入门到掌握」🏆 本文收录于《Spring B - 掘金 (juejin.cn)</a></p>
<h2 id="云盘"><a href="#云盘" class="headerlink" title="云盘"></a>云盘</h2><blockquote>
<p>2025 年 1 月 16 日</p>
</blockquote>
<p>百度网盘 115G，阿里云盘 105G，夸克云盘 10G，迅雷云盘 1TB。</p>
<blockquote>
<p>2025 年 1 月 17 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_43501408/article/details/140227016">onedeive 作用是什么，类似百度网盘吗，和百度网盘有什么区别没？_one deive-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://www.zhihu.com/question/516252714/answer/2955470027">(18 封私信 / 7 条消息) 为什么微软的网盘 Onedrive 不像百度网盘一样支持秒传呢？ - 知乎 (zhihu.com)</a></p>
<p>阿里云盘用来同步备份，百度网盘用来上传保存，夸克云盘用来及时救急，迅雷云盘当然是用来下载文件了。</p>
<p>妈的，百度网盘上传文件大小受到限制，超过 4GB 就得花钱了；迅雷云盘更夸张，稍微大点有个 1G 就上传失败，看看阿里云盘。</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs stata">‌百度网盘普通用户单个文件上传的最大限制为4GB，而会员用户可以享受更大的上传空间。具体来说，百度网盘超级会员（SVIP）用户在使用Windows客户端和<span class="hljs-keyword">Mac</span>客户端进行大文件上传时，可以上传的最大文件大小如下：<br>‌普通用户‌：单个文件最大上传限制为4GB。<br>‌会员用户‌：最大可上传单个文件至20GB。<br>‌超级会员（SVIP）‌：使用Windows客户端和<span class="hljs-keyword">Mac</span>客户端进行大文件上传时，超级会员V1可上传300G大文件，超级会员V10最高可上传2048G超大文件。<br>不同用户类型的上传限制<br>‌普通用户‌：普通用户的总存储空间为2TB，单个文件最大上传限制为4GB。<br>‌会员用户‌：会员用户的总存储空间和上传速度会有所提升，单个文件最大上传限制为20GB。<br>‌超级会员（SVIP）‌：超级会员在Windows客户端和<span class="hljs-keyword">Mac</span>客户端上可以上传更大文件，具体大小取决于会员等级，从300G到2048G不等。<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/tang7mj/article/details/143231466">9.4 文件的上传和下载-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://eyun.baidu.com/content/56866/">阿里云盘普通用户限制多久 | 百度网盘企业版 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1711019996564106268&wfr=spider&for=pc">我的此电脑设备和驱动器里的百度网盘图标怎么删除？ (baidu.com)</a></p>
<figure class="highlight moonscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs moonscript">计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250117154128751.png" alt="image-20250117154128751"></p>
<h2 id="DeepSeek"><a href="#DeepSeek" class="headerlink" title="DeepSeek"></a>DeepSeek</h2><blockquote>
<p>2025 年 2 月 13 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/sinat_29950703/article/details/143431471">ChatBox 可以免费对话 Gemini 和 Claude 千次-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/zhishi0000/article/details/145478600?ops_request_misc=%7B%22request_id%22:%2233134c0f65c73e4fe61e5dd4bc27dec1%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=33134c0f65c73e4fe61e5dd4bc27dec1&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-145478600-null-null.142%5Ev101%5Econtrol&utm_term=%E6%9C%AC%E6%9C%BA%E9%83%A8%E7%BD%B2DeepSeek&spm=1018.2226.3001.4187">DeepSeek 本地化部署全攻略，轻松拥有专属 AI 助手-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/zhishi0000/article/details/145479026?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%9C%AC%E6%9C%BA%E9%83%A8%E7%BD%B2DeepSeek&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-145479026.142%5Ev101%5Econtrol&spm=1018.2226.3001.4187">本地免费部署 DeepSeek 教程，个人 PC 都能安装（附软件）_个人电脑部署 deepseek-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_39074599/article/details/145499380?ops_request_misc=%7B%22request_id%22:%2233134c0f65c73e4fe61e5dd4bc27dec1%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=33134c0f65c73e4fe61e5dd4bc27dec1&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-3-145499380-null-null.142%5Ev101%5Econtrol&utm_term=%E6%9C%AC%E6%9C%BA%E9%83%A8%E7%BD%B2DeepSeek&spm=1018.2226.3001.4187">攻略丨搭建属于自己的 DeepSeek，本地部署「手搓教程」在此！_本地搭建 deepseek-CSDN 博客</a></p>
<blockquote>
<p>2025 年 2 月 14 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_17153885/article/details/140835601?ops_request_misc=%7B%22request_id%22:%224b28004050691c645267c87527a8d011%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=4b28004050691c645267c87527a8d011&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-140835601-null-null.142%5Ev101%5Econtrol&utm_term=%E5%BF%AB%E9%80%9F%E6%8E%A5%E5%85%A5ai%E5%A4%A7%E6%A8%A1%E5%9E%8B&spm=1018.2226.3001.4187">10 分钟接入 AI 大模型—Spring Cloud Alibaba_spring ai-CSDN 博客</a></p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs">企业方面，大模型将带来数智化升级的进一步加速。举几个例子，通过大模型可以实现：<br>金融领域中的投资组合优化、风险管理、欺诈检测等；<br>医疗领域中疾病预测、药物研发、医疗影像分析等；<br>制造业中的生产计划排程、质量控制、物流管理等；<br>交通运输领域中的自动驾驶、智能交通管理等；<br>娱乐领域中游戏开发、电影制作、音乐创作等。<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/ytt0523_com/article/details/139143909?ops_request_misc=%7B%22request_id%22:%224b28004050691c645267c87527a8d011%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=4b28004050691c645267c87527a8d011&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-139143909-null-null.142%5Ev101%5Econtrol&utm_term=%E5%BF%AB%E9%80%9F%E6%8E%A5%E5%85%A5ai%E5%A4%A7%E6%A8%A1%E5%9E%8B&spm=1018.2226.3001.4187">从头开始，八步实现大模型接入｜如何用好大模型-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1815807787586193063&wfr=spider&for=pc">2024 年末 AI 大模型盘点：国内外当前主流大数据模型汇总 (baidu.com)</a></p>
<p>国内：<strong>文心一言</strong> ，<strong>豆包</strong>，<strong>Kimi</strong>，<strong>讯飞星火</strong>，<strong>智谱清言</strong>，<strong>通义千问</strong>，<strong>腾讯元宝</strong>，<strong>天工 AI</strong>，<strong>盘古</strong>，<strong>赤兔</strong></p>
<p>国外：<strong>GPT 系列</strong> ，<strong>Gemini 系列</strong>，<strong>Claude 系列</strong></p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1823375893043970182&wfr=spider&for=pc">2025 年全球 AI 大模型盘点及对比分析 (baidu.com)</a></p>
<p><strong>AI 模型接入</strong></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_25987725/article/details/140707462?ops_request_misc=%7B%22request_id%22:%22a16eeff352bdfc08865d70531f0bae72%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=a16eeff352bdfc08865d70531f0bae72&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-140707462-null-null.142%5Ev101%5Econtrol&utm_term=springboot%E6%8E%A5%E5%85%A5%E6%96%87%E5%BF%83%E4%B8%80%E8%A8%80&spm=1018.2226.3001.4187">Spring Boot 对接文心一言_springboot 接入文心一言-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_61931726/article/details/138467475?ops_request_misc=%7B%22request_id%22:%22a16eeff352bdfc08865d70531f0bae72%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=a16eeff352bdfc08865d70531f0bae72&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-3-138467475-null-null.142%5Ev101%5Econtrol&utm_term=springboot%E6%8E%A5%E5%85%A5%E6%96%87%E5%BF%83%E4%B8%80%E8%A8%80&spm=1018.2226.3001.4187">springboot+vue 项目接入文心一言 API_springboot 接入文心一言-CSDN 博客</a></p>
<blockquote>
<p>2025 年 2 月 17 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/max202011161630/article/details/145392788?ops_request_misc=%7B%22request_id%22:%2248b8e7430ee6dd3972571c66795a5d08%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=48b8e7430ee6dd3972571c66795a5d08&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-145392788-null-null.142%5Ev101%5Econtrol&utm_term=DeepSeek%E6%80%8E%E4%B9%88%E8%AE%AD%E7%BB%83&spm=1018.2226.3001.4187">DeepSeek R1 使用指南：架构、训练、本地部署_deepseek 本地训练-CSDN 博客</a></p>
<blockquote>
<p>2025 年 2 月 19 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/suyuan2022/article/details/145387822">99%的人都不知道的 DeepSeek 玩法：榨干算力，性能狂飙！_深度思考 r1 选与不选的区别-CSDN 博客</a></p>
<p><strong>用朴实直白的语言，不要过度发挥或创造新名词，避免使用过于专业的术语或自创概念。</strong></p>
<p><a target="_blank" rel="noopener" href="https://tieba.baidu.com/p/9487767516">【图片】这四个模式都是什么意思，有什么区别吗？【deepseek 吧】_百度贴吧 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://tieba.baidu.com/p/9491582461">【图片】【关于深度思考】deepseek 说开不开深度思考不影响答案本身<em>deepseek 吧</em>百度贴吧 (baidu.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7464586294558195763">手把手教你在本地部署 DeepSeek R1，搭建 web-ui ，建议收藏！写在前面 最近，DeepSeek 发布的推理大 - 掘金 (juejin.cn)</a></p>
<blockquote>
<p>2025 年 2 月 21 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/23498477337">DeepSeek+KIMI 超强组合，一人就是一家公司! 保姆级教程 - 知乎 (zhihu.com)</a></p>
<h2 id="Conda"><a href="#Conda" class="headerlink" title="Conda"></a>Conda</h2><blockquote>
<p>2025 年 2 月 21 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/coder_oldgeek/article/details/122239755">conda 环境管理与包安装实战-CSDN 博客</a></p>
<h2 id="权限认证"><a href="#权限认证" class="headerlink" title="权限认证"></a>权限认证</h2><blockquote>
<p>2025 年 2 月 27 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_45541665/article/details/143718529">Spring Security 认证流程，长话简说_springsecurity 认证流程-CSDN 博客</a></p>
<h2 id="无人机"><a href="#无人机" class="headerlink" title="无人机"></a>无人机</h2><blockquote>
<p>2025 年 3 月 17 日</p>
</blockquote>
<p>[大疆无人机上云 API：Java 代码实战全攻略-CSDN 博客](<a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_73978383/article/details/146033672?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=Java">https://blog.csdn.net/m0_73978383/article/details/146033672?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=Java</a> 无人机&amp;utm_medium=distribute.pc_search_result.none-task-blog-2<del>all</del>sobaiduweb~default-8-146033672.142^v102^control&amp;spm=1018.2226.3001.4187)</p>
<p>[无人机飞行数据 java 版本 api 大疆无人机 SpringBoot_大疆无人机视频数据实时传输 api-CSDN 博客](<a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_38821574/article/details/123356320?ops_request_misc=%7B%22request_id%22:%22a21ae00631af52d8a114d4d7be5d89b3%22,%22scm%22:%2220140713.130102334.pc_all.%22%7D&amp;request_id=a21ae00631af52d8a114d4d7be5d89b3&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-8-123356320-null-null.142%5Ev102%5Econtrol&amp;utm_term=Java">https://blog.csdn.net/qq_38821574/article/details/123356320?ops_request_misc=%7B%22request%5Fid%22%3A%22a21ae00631af52d8a114d4d7be5d89b3%22%2C%22scm%22%3A%2220140713.130102334.pc%5Fall.%22%7D&amp;request_id=a21ae00631af52d8a114d4d7be5d89b3&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-8-123356320-null-null.142^v102^control&amp;utm_term=Java</a> 无人机&amp;spm=1018.2226.3001.4187)</p>
<h2 id="Mybatis"><a href="#Mybatis" class="headerlink" title="Mybatis"></a>Mybatis</h2><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/vcj1009784814/article/details/106391982?spm=1001.2014.3001.5506">mybatis 看这一篇就够了，简单全面一发入魂_mybatis 一发入魂-CSDN 博客</a></p>
<h2 id="SQL"><a href="#SQL" class="headerlink" title="SQL"></a>SQL</h2><h2 id="Netty"><a href="#Netty" class="headerlink" title="Netty"></a>Netty</h2><blockquote>
<p>2025 年 3 月 17 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_48016395/article/details/123859626?ops_request_misc=%7B%22request_id%22:%22243e44ad6b95410c591024448906f399%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=243e44ad6b95410c591024448906f399&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-123859626-null-null.142%5Ev102%5Econtrol&utm_term=%E5%90%8C%E6%AD%A5%E5%BC%82%E6%AD%A5%E9%98%BB%E5%A1%9E%E9%9D%9E%E9%98%BB%E5%A1%9E&spm=1018.2226.3001.4187">理解：什么是同步和异步？什么是阻塞和非阻塞？_什么是同步什么是异步-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_35190492/article/details/113174359?ops_request_misc=%7B%22request_id%22:%22517f776b1f5c2f54b42cc2703344a6c8%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=517f776b1f5c2f54b42cc2703344a6c8&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-113174359-null-null.142%5Ev102%5Econtrol&utm_term=Netty&spm=1018.2226.3001.4187">【硬核】肝了一月的 Netty 知识点-CSDN 博客</a></p>
<p>[01 初识 Netty：为什么 Netty 这么流行？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Netty">https://learn.lianglianglee.com/专栏/Netty</a> 核心原理剖析与 RPC 实践-完/01 初识 Netty：为什么 Netty 这么流行？.md)</p>
<h2 id="消息队列"><a href="#消息队列" class="headerlink" title="消息队列"></a>消息队列</h2><blockquote>
<p>2025 年 3 月 17 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_42039228/article/details/123493937?ops_request_misc=%7B%22request_id%22:%224f2bf870f640e7839b87c14bbcaa11c8%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=4f2bf870f640e7839b87c14bbcaa11c8&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-123493937-null-null.142%5Ev102%5Econtrol&utm_term=RabbitMQ&spm=1018.2226.3001.4187">RabbitMQ 详解，用心看完这一篇就够了【重点】-CSDN 博客</a></p>
<h2 id="Node"><a href="#Node" class="headerlink" title="Node"></a>Node</h2><blockquote>
<p>2025 年 3 月 18 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_42006801/article/details/124830995?ops_request_misc=%7B%22request_id%22:%2219e493c3995c85cbe2d696352a16acd5%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=19e493c3995c85cbe2d696352a16acd5&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-124830995-null-null.142%5Ev102%5Econtrol&utm_term=Node&spm=1018.2226.3001.4187">Node.js 安装与配置（详细步骤）_nodejs 安装及环境配置-CSDN 博客</a></p>
<h2 id="SpringBoot"><a href="#SpringBoot" class="headerlink" title="SpringBoot"></a>SpringBoot</h2><blockquote>
<p>2025 年 3 月 18 日</p>
</blockquote>
<p>[09 数据抽象：Spring Data 如何对数据访问过程进行统一抽象？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/09 数据抽象：Spring Data 如何对数据访问过程进行统一抽象？.md)</p>
<p>[17 安全架构：如何理解 Spring 安全体系的整体架构？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/17 安全架构：如何理解 Spring 安全体系的整体架构？.md)</p>
<p>全面梳理基于 Spring Boot 的 Web 应用程序开发技术组件，其中包括配置体系、数据访问、Web 服务、消息通信、系统安全、系统监控、系统测试等专项主题。这些技术组件涵盖了 Java EE 应用程序开发涉及的方方面面，具有广泛的应用场景。</p>
<p>Spring Boot 可以帮助我们构建从 Web 服务层到数据访问层的全栈式响应式编程技术，从而确保系统的各个环节都具备即时响应性。</p>
<h2 id="回调"><a href="#回调" class="headerlink" title="回调"></a>回调</h2><blockquote>
<p>2025 年 3 月 18 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/Tomkruse11/article/details/144350534?ops_request_misc=%7B%22request_id%22:%22ce19e35a4a7aa78bad87234512474669%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=ce19e35a4a7aa78bad87234512474669&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-144350534-null-null.142%5Ev102%5Econtrol&utm_term=%E5%9B%9E%E8%B0%83%E6%9C%BA%E5%88%B6&spm=1018.2226.3001.4187">回调机制详解-CSDN 博客</a></p>
<h2 id="七牛云"><a href="#七牛云" class="headerlink" title="七牛云"></a>七牛云</h2><blockquote>
<p>2025 年 4 月 26 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7331176540703784987?searchId=202504261811438DE0A034B96F77EE30C8">Java21 + SpringBoot3 集成七牛云对象存储 OSS，实现文件上传前言 实现步骤 引入 maven 依赖 修改配 - 掘金 (juejin.cn)</a></p>
<p>导入 Maven 依赖。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>  <span class="hljs-comment">&lt;!-- 七牛云SDK --&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.qiniu<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>qiniu-java-sdk<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>[7.13.0, 7.13.99]<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>  <span class="hljs-comment">&lt;!-- Lombok --&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.projectlombok<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>lombok<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.18.30<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">optional</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">optional</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>新增配置信息。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">fast-alden:</span><br>  <span class="hljs-attr">file:</span><br>    <span class="hljs-attr">oss:</span><br>      <span class="hljs-attr">qiniu:</span><br>        <span class="hljs-attr">access-key:</span> <span class="hljs-string">******************************</span> <span class="hljs-comment"># 请从七牛云工作台-个人中心-密钥管理获取</span><br>        <span class="hljs-attr">secret-key:</span> <span class="hljs-string">******************************-KL01</span> <span class="hljs-comment"># 请从七牛云工作台-个人中心-密钥管理获取</span><br>        <span class="hljs-attr">bucket:</span> <span class="hljs-string">memory-blog</span> <span class="hljs-comment"># 七牛云存储空间名称</span><br>        <span class="hljs-attr">directory:</span> <span class="hljs-string">/</span> <span class="hljs-comment"># 自定义存储空间内目录</span><br>        <span class="hljs-attr">domain:</span> <span class="hljs-string">blog.memory-life.xyz</span> <span class="hljs-comment"># 存储空间自定义域名，请提前在存储空间中进行配置</span><br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250426182122767.png" alt="image-20250426182122767"></p>
<p>创建七牛云服务配置类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 七牛云OSS相关配置</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-meta">@ConfigurationProperties(prefix = &quot;fast-alden.file.oss.qiniu&quot;)</span><br><span class="hljs-meta">@Getter</span><br><span class="hljs-meta">@Setter</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">QiniuConfig</span> &#123;<br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * AC</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> String accessKey;<br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * SC</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> String secretKey;<br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 存储空间</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> String bucket;<br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 上传目录</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> String directory;<br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 访问域名</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> String domain;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>编写文件操作服务接口。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 文件操作服务</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">FileService</span> &#123;<br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 文件上传</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> file 待上传的文件</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span> 访问该文件的url</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@throws</span> IOException</span><br><span class="hljs-comment">     */</span><br>    String <span class="hljs-title function_">upload</span><span class="hljs-params">(MultipartFile file)</span> <span class="hljs-keyword">throws</span> IOException;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>实现文件操作服务类接口。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 七牛云对象存储文件服务</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Service(&quot;fileService&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">QiniuFileServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">FileService</span> &#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> QiniuConfig qiniuConfig;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">QiniuFileServiceImpl</span><span class="hljs-params">(QiniuConfig qiniuConfig)</span> &#123;<br>        <span class="hljs-built_in">this</span>.qiniuConfig = qiniuConfig;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">upload</span><span class="hljs-params">(MultipartFile file)</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>        <span class="hljs-keyword">if</span> (file.isEmpty()) &#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">&quot;文件是空的&quot;</span>);<br>        &#125;<br>        <span class="hljs-comment">// 创建上传token</span><br>        <span class="hljs-type">Auth</span> <span class="hljs-variable">auth</span> <span class="hljs-operator">=</span> Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());<br>        <span class="hljs-type">String</span> <span class="hljs-variable">upToken</span> <span class="hljs-operator">=</span> auth.uploadToken(qiniuConfig.getBucket());<br><br>        <span class="hljs-comment">// 设置上传配置，Region要与存储空间所属的存储区域保持一致</span><br>        <span class="hljs-type">Configuration</span> <span class="hljs-variable">cfg</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Configuration</span>(Region.huadongZheJiang2());<br><br>        <span class="hljs-comment">// 创建上传管理器</span><br>        <span class="hljs-type">UploadManager</span> <span class="hljs-variable">uploadManager</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UploadManager</span>(cfg);<br><br>        <span class="hljs-type">String</span> <span class="hljs-variable">originalFilename</span> <span class="hljs-operator">=</span> file.getOriginalFilename();<br>        <span class="hljs-comment">// 构造文件目录和文件名</span><br>        <span class="hljs-keyword">assert</span> originalFilename != <span class="hljs-literal">null</span>;<br>        <span class="hljs-type">String</span> <span class="hljs-variable">suffix</span> <span class="hljs-operator">=</span> originalFilename.substring(originalFilename.lastIndexOf(<span class="hljs-string">&quot;.&quot;</span>));<br>        <span class="hljs-type">String</span> <span class="hljs-variable">fileKey</span> <span class="hljs-operator">=</span> qiniuConfig.getDirectory() + UUID.randomUUID() + suffix;<br><br>        <span class="hljs-comment">// 上传文件</span><br>        <span class="hljs-type">Response</span> <span class="hljs-variable">response</span> <span class="hljs-operator">=</span> uploadManager.put(file.getInputStream(), fileKey, upToken, <span class="hljs-literal">null</span>, <span class="hljs-literal">null</span>);<br><br>        <span class="hljs-comment">// 返回文件url</span><br>        <span class="hljs-keyword">return</span> qiniuConfig.getDomain() + fileKey;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>上述代码中有一行用到了<code>Region.huadongZheJiang2()</code>，此处要与自己的存储空间所属的存储区域保持一致，本文中所使用的存储空间属于<code>华东-浙江2</code>区域。</p>
<p>创建控制器类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@RestController</span><br><span class="hljs-meta">@RequestMapping(&quot;/file&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">FileController</span> &#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> FileService fileService;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">FileController</span><span class="hljs-params">(FileService fileService)</span> &#123;<br>        <span class="hljs-built_in">this</span>.fileService = fileService;<br>    &#125;<br><br>    <span class="hljs-meta">@PostMapping(&quot;/upload&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">upload</span><span class="hljs-params">(MultipartFile multipartFile)</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>        <span class="hljs-keyword">return</span> fileService.upload(multipartFile);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>Postman 测试下。</p>
<p><img src="http://blog.memory-life.xyz/image-20250426190924217.png" alt="image-20250426190924217"></p>
<p>请求类型要用 POST 啊，要不返回结果就是这样，看半天没看出问题，到后台找日志才明白。</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;timestamp&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;2025-04-26T11:11:10.502+00:00&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;status&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">400</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;error&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;Bad Request&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;path&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;/admin/login&quot;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs stylus"><span class="hljs-number">8080</span>-exec-<span class="hljs-number">7</span>] com<span class="hljs-selector-class">.macro</span><span class="hljs-selector-class">.mall</span><span class="hljs-selector-class">.common</span><span class="hljs-selector-class">.log</span><span class="hljs-selector-class">.WebLogAspect</span>   : &#123;<span class="hljs-string">&quot;description&quot;</span>:<span class="hljs-string">&quot;登录以后返回token&quot;</span>,<span class="hljs-string">&quot;username&quot;</span>:<span class="hljs-string">&quot;admin&quot;</span>,<span class="hljs-string">&quot;startTime&quot;</span>:<span class="hljs-number">1745665865918</span>,<span class="hljs-string">&quot;spendTime&quot;</span>:<span class="hljs-number">101</span>,<span class="hljs-string">&quot;basePath&quot;</span>:<span class="hljs-string">&quot;http://localhost:8080&quot;</span>,<span class="hljs-string">&quot;uri&quot;</span>:<span class="hljs-string">&quot;/admin/login&quot;</span>,<span class="hljs-string">&quot;url&quot;</span>:<span class="hljs-string">&quot;http://localhost:8080/admin/login&quot;</span>,<span class="hljs-string">&quot;method&quot;</span>:<span class="hljs-string">&quot;POST&quot;</span>,<span class="hljs-string">&quot;ip&quot;</span>:<span class="hljs-string">&quot;192.168.1.11&quot;</span>,<span class="hljs-string">&quot;parameter&quot;</span>:&#123;<span class="hljs-string">&quot;username&quot;</span>:<span class="hljs-string">&quot;admin&quot;</span>,<span class="hljs-string">&quot;password&quot;</span>:<span class="hljs-string">&quot;macro123&quot;</span>&#125;,<span class="hljs-string">&quot;result&quot;</span>:&#123;<span class="hljs-string">&quot;code&quot;</span>:<span class="hljs-number">200</span>,<span class="hljs-string">&quot;message&quot;</span>:<span class="hljs-string">&quot;操作成功&quot;</span>,<span class="hljs-string">&quot;data&quot;</span>:&#123;<span class="hljs-string">&quot;tokenHead&quot;</span>:<span class="hljs-string">&quot;Bearer &quot;</span>,<span class="hljs-string">&quot;token&quot;</span>:<span class="hljs-string">&quot;eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImNyZWF0ZWQiOjE3NDU2NjU4NjYwMTAsImV4cCI6MTc0NjI3MDY2Nn0.X62Muzq1P4MN9I2CLIrBEaHPMN2MP_4_EmZ9q0LgJSvFXnokpW_zHpwsvbuOCPovWyvbIhZwcAVxBiDaJUOGeA&quot;</span>&#125;&#125;&#125;<br><span class="hljs-number">2025</span>-<span class="hljs-number">04</span>-<span class="hljs-number">26</span> <span class="hljs-number">19</span>:<span class="hljs-number">11</span>:<span class="hljs-number">10.496</span>  INFO <span class="hljs-number">9940</span> --- <span class="hljs-selector-attr">[nio-8080-exec-3]</span> c<span class="hljs-selector-class">.m</span><span class="hljs-selector-class">.m</span><span class="hljs-selector-class">.s</span><span class="hljs-selector-class">.c</span><span class="hljs-selector-class">.JwtAuthenticationTokenFilter</span>   : checking username:admin<br><span class="hljs-number">2025</span>-<span class="hljs-number">04</span>-<span class="hljs-number">26</span> <span class="hljs-number">19</span>:<span class="hljs-number">11</span>:<span class="hljs-number">10.499</span>  INFO <span class="hljs-number">9940</span> --- <span class="hljs-selector-attr">[nio-8080-exec-3]</span> c<span class="hljs-selector-class">.m</span><span class="hljs-selector-class">.m</span><span class="hljs-selector-class">.s</span><span class="hljs-selector-class">.c</span><span class="hljs-selector-class">.JwtAuthenticationTokenFilter</span>   : authenticated user:admin<br><span class="hljs-number">2025</span>-<span class="hljs-number">04</span>-<span class="hljs-number">26</span> <span class="hljs-number">19</span>:<span class="hljs-number">11</span>:<span class="hljs-number">10.501</span>  WARN <span class="hljs-number">9940</span> --- <span class="hljs-selector-attr">[nio-8080-exec-3]</span> <span class="hljs-selector-class">.w</span><span class="hljs-selector-class">.s</span><span class="hljs-selector-class">.m</span><span class="hljs-selector-class">.s</span><span class="hljs-selector-class">.DefaultHandlerExceptionResolver</span> : Resolved <span class="hljs-selector-attr">[org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type <span class="hljs-string">&#x27;java.lang.String&#x27;</span> to required type <span class="hljs-string">&#x27;java.lang.Long&#x27;</span>; nested exception is java.lang.NumberFormatException: For input string: <span class="hljs-string">&quot;login&quot;</span>]</span><br><span class="hljs-number">2025</span>-<span class="hljs-number">04</span>-<span class="hljs-number">26</span> <span class="hljs-number">19</span>:<span class="hljs-number">11</span>:<span class="hljs-number">10.502</span> DEBUG <span class="hljs-number">9940</span> --- <span class="hljs-selector-attr">[nio-8080-exec-3]</span> c<span class="hljs-selector-class">.m</span><span class="hljs-selector-class">.m</span><span class="hljs-selector-class">.s</span><span class="hljs-selector-class">.component</span><span class="hljs-selector-class">.DynamicSecurityFilter</span>  : Authorized public <span class="hljs-selector-tag">object</span> <span class="hljs-attribute">filter</span> invocation [GET /error]<br></code></pre></td></tr></table></figure>

<p>显然这次成功了，顺利。</p>
<p><img src="http://blog.memory-life.xyz/image-20250426191234129.png" alt="image-20250426191234129"></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br>  <span class="hljs-attr">&quot;timestamp&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;2025-04-26T11:14:42.287+00:00&quot;</span><span class="hljs-punctuation">,</span><br>  <span class="hljs-attr">&quot;status&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">404</span><span class="hljs-punctuation">,</span><br>  <span class="hljs-attr">&quot;error&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;Not Found&quot;</span><span class="hljs-punctuation">,</span><br>  <span class="hljs-attr">&quot;path&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;/file/upload&quot;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p>一直显示未找到服务，原来是代码修改完毕后没重启服务。</p>
<p><img src="http://blog.memory-life.xyz/image-20250426192513683.png" alt="image-20250426192513683"></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">2025-04-26 19:18:39.666 DEBUG 1932 --- [nio-8080-exec-5] c.m.m.s.component.DynamicSecurityFilter  : Authorized public object filter invocation [POST /file/upload]<br>2025-04-26 19:18:39.667 DEBUG 1932 --- [nio-8080-exec-5] c.m.m.s.component.DynamicSecurityFilter  : Authorized public object filter invocation [POST /file/upload]<br>2025-04-26 19:18:46.330  INFO 1932 --- [nio-8080-exec-5] com.macro.mall.common.log.WebLogAspect   : &#123;<span class="hljs-string">&quot;username&quot;</span>:<span class="hljs-string">&quot;admin&quot;</span>,<span class="hljs-string">&quot;startTime&quot;</span>:1745666319732,<span class="hljs-string">&quot;spendTime&quot;</span>:6596,<span class="hljs-string">&quot;basePath&quot;</span>:<span class="hljs-string">&quot;http://localhost:8080&quot;</span>,<span class="hljs-string">&quot;uri&quot;</span>:<span class="hljs-string">&quot;/file/upload&quot;</span>,<span class="hljs-string">&quot;url&quot;</span>:<span class="hljs-string">&quot;http://localhost:8080/file/upload&quot;</span>,<span class="hljs-string">&quot;method&quot;</span>:<span class="hljs-string">&quot;POST&quot;</span>,<span class="hljs-string">&quot;ip&quot;</span>:<span class="hljs-string">&quot;192.168.1.11&quot;</span>,<span class="hljs-string">&quot;result&quot;</span>:<span class="hljs-string">&quot;blog.memory-life.xyz/f585f679-78ae-498d-bbe2-290ffd0f99c5.jpg&quot;</span>&#125;<br></code></pre></td></tr></table></figure>

<p>上传至七牛云成功，不过需要注意下配置上传目录。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">fast-alden:</span><br>  <span class="hljs-attr">file:</span><br>    <span class="hljs-attr">oss:</span><br>      <span class="hljs-attr">qiniu:</span><br>        <span class="hljs-attr">access-key:</span> <span class="hljs-string">******************************</span> <span class="hljs-comment"># 请从七牛云工作台-个人中心-密钥管理获取</span><br>        <span class="hljs-attr">secret-key:</span> <span class="hljs-string">******************************-KL01</span> <span class="hljs-comment"># 请从七牛云工作台-个人中心-密钥管理获取</span><br>        <span class="hljs-attr">bucket:</span> <span class="hljs-string">memory-blog</span> <span class="hljs-comment"># 七牛云存储空间名称</span><br>        <span class="hljs-attr">directory:</span> <span class="hljs-string">mall/</span> <span class="hljs-comment"># 自定义存储空间内目录</span><br>        <span class="hljs-attr">domain:</span> <span class="hljs-string">blog.memory-life.xyz/</span> <span class="hljs-comment"># 存储空间自定义域名，请提前在存储空间中进行配置</span><br></code></pre></td></tr></table></figure>

<p>前台。</p>
<p><a target="_blank" rel="noopener" href="https://element.eleme.cn/#/zh-CN/component/upload">组件 | Element</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_57998947/article/details/130846268">element ui 文件或者图片上传（包括自定义上传）_element 实现 icon 上传按钮-CSDN 博客</a></p>
<p>累了，明天再搞。</p>
<p>学编程这么多年，竟然连前端页面上传图片调用后端接口，这么简单的功能都做不了。</p>
<p>要说这前端就是费劲，官网文档写得跟几把一样。</p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/mahmud/p/16931006.html">ElementUI 实现图片上传的功能 🌈~（已完成 ✔） - Mahmud(مەھمۇد) - 博客园 (cnblogs.com)</a></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;el-form-item label=&quot;商品相册：&quot;&gt;&lt;el-upload<br>          class=&quot;upload-demo&quot;<br>          action=&quot;http://localhost:8080/file/upload&quot;<br>          :on-preview=&quot;handlePreview&quot;<br>          :on-remove=&quot;handleRemove&quot;<br>          :file-list=&quot;fileList&quot;<br>          list-type=&quot;picture&quot;<br>          :headers=&quot;headersObj&quot;<br>        &gt;<br>          &lt;el-button size=&quot;small&quot; type=&quot;primary&quot;&gt;点击上传&lt;/el-button&gt;<br>        &lt;/el-upload&gt;<br>      &lt;/el-form-item&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// 图片上传组件添加Authorization请求头对象，</span><br><span class="hljs-comment">// 每一次方式请求都有了token请求头，从session里拿到</span><br><span class="hljs-attr">headersObj</span>: &#123;<br>  <span class="hljs-title class_">Authorization</span>: <span class="hljs-variable language_">window</span>.<span class="hljs-property">sessionStorage</span>.<span class="hljs-title function_">getItem</span>(<span class="hljs-string">&quot;token&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>标记了后台接口地址，这次上传顺利了，不过有个 Token 问题需要解决。</p>
<p><img src="http://blog.memory-life.xyz/image-20250426215319399.png" alt="image-20250426215319399"></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br>  <span class="hljs-attr">&quot;code&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">401</span><span class="hljs-punctuation">,</span><br>  <span class="hljs-attr">&quot;message&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;暂未登录或token已经过期&quot;</span><span class="hljs-punctuation">,</span><br>  <span class="hljs-attr">&quot;data&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;Full authentication is required to access this resource&quot;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p>后台拿到的 Token 总是 null，为什么。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment">    * 从token中获取JWT中的负载</span><br><span class="hljs-comment">    */</span><br>   <span class="hljs-keyword">private</span> Claims <span class="hljs-title function_">getClaimsFromToken</span><span class="hljs-params">(String token)</span> &#123;<br>       <span class="hljs-type">Claims</span> <span class="hljs-variable">claims</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>       <span class="hljs-keyword">try</span> &#123;<br>           claims = Jwts.parser()<br>                   .setSigningKey(secret)<br>                   .parseClaimsJws(token)<br>                   .getBody();<br>       &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>           LOGGER.info(<span class="hljs-string">&quot;JWT格式验证失败:&#123;&#125;&quot;</span>, token);<br>       &#125;<br>       <span class="hljs-keyword">return</span> claims;<br>   &#125;<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_51963973/article/details/125976367">element-ui 实现图片上传功能（前台部分）_elementui 上传图片-CSDN 博客</a></p>
<p>看到 request.js 里写明确了 Token 获取以及设置方法，每个请求都会携带 Token：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// request拦截器</span><br>service.<span class="hljs-property">interceptors</span>.<span class="hljs-property">request</span>.<span class="hljs-title function_">use</span>(<br>  <span class="hljs-function">(<span class="hljs-params">config</span>) =&gt;</span> &#123;<br>    <span class="hljs-keyword">if</span> (store.<span class="hljs-property">getters</span>.<span class="hljs-property">token</span>) &#123;<br>      config.<span class="hljs-property">headers</span>[<span class="hljs-string">&quot;Authorization&quot;</span>] = <span class="hljs-title function_">getToken</span>(); <span class="hljs-comment">// 让每个请求携带自定义token 请根据实际情况自行修改</span><br>    &#125;<br>    <span class="hljs-keyword">return</span> config;<br>  &#125;,<br>  <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// Do something with request error</span><br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(error); <span class="hljs-comment">// for debug</span><br>    <span class="hljs-title class_">Promise</span>.<span class="hljs-title function_">reject</span>(error);<br>  &#125;<br>);<br></code></pre></td></tr></table></figure>

<p>auth.js 里明确了方法实现。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> <span class="hljs-title class_">TokenKey</span> = <span class="hljs-string">&quot;loginToken&quot;</span>;<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">getToken</span>(<span class="hljs-params"></span>) &#123;<br>  <span class="hljs-keyword">return</span> <span class="hljs-title class_">Cookies</span>.<span class="hljs-title function_">get</span>(<span class="hljs-title class_">TokenKey</span>);<br>&#125;<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">setToken</span>(<span class="hljs-params">token</span>) &#123;<br>  <span class="hljs-keyword">return</span> <span class="hljs-title class_">Cookies</span>.<span class="hljs-title function_">set</span>(<span class="hljs-title class_">TokenKey</span>, token);<br>&#125;<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">removeToken</span>(<span class="hljs-params"></span>) &#123;<br>  <span class="hljs-keyword">return</span> <span class="hljs-title class_">Cookies</span>.<span class="hljs-title function_">remove</span>(<span class="hljs-title class_">TokenKey</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>el-upload 组件内如此设置请求头：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;el-upload<br>  class=&quot;upload-demo&quot;<br>  action=&quot;http://localhost:8080/file/upload&quot;<br>  :on-preview=&quot;handlePreview&quot;<br>  :on-remove=&quot;handleRemove&quot;<br>  :file-list=&quot;fileList&quot;<br>  list-type=&quot;picture&quot;<br>  :headers=&quot;headers&quot;<br>&gt;<br>          &lt;el-button size=&quot;small&quot; type=&quot;primary&quot;&gt;点击上传&lt;/el-button&gt;<br>        &lt;/el-upload&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> &#123; getToken &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@/utils/auth&quot;</span>;<br><br><span class="hljs-comment">// 图片上传组件添加Authorization请求头对象，</span><br><span class="hljs-comment">// 每一次方式请求都有了token请求头，从session里拿到</span><br><span class="hljs-attr">headers</span>: &#123;<br>  <span class="hljs-title class_">Authorization</span>: <span class="hljs-title function_">getToken</span>(); <span class="hljs-comment">// 从 localStorage 获取 token</span><br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250426221916269.png" alt="image-20250426221916269"></p>
<p>直接调用就行，不需要多于拼接，要不然会遇到如上问题。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 从token中获取JWT中的负载</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">private</span> Claims <span class="hljs-title function_">getClaimsFromToken</span><span class="hljs-params">(String token)</span> &#123;<br>    <span class="hljs-type">Claims</span> <span class="hljs-variable">claims</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>    <span class="hljs-keyword">try</span> &#123;<br>        claims = Jwts.parser()<br>                .setSigningKey(secret)<br>                .parseClaimsJws(token)<br>                .getBody();<br>    &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;<br>        LOGGER.info(<span class="hljs-string">&quot;JWT格式验证失败:&#123;&#125;&quot;</span>, token);<br>    &#125;<br>    <span class="hljs-keyword">return</span> claims;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>后端过滤器顺利校验通过，再检查下图片上传效果。</p>
<p>已经能够请求到后台服务接口了，不过接收到的图片参数为 null。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@PostMapping(&quot;/upload&quot;)</span><br>   <span class="hljs-keyword">public</span> String <span class="hljs-title function_">upload</span><span class="hljs-params">(MultipartFile multipartFile)</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>       <span class="hljs-keyword">return</span> fileService.upload(multipartFile);<br>   &#125;<br></code></pre></td></tr></table></figure>

<p>在 Element UI 的 <code>&lt;el-upload&gt;</code> 组件中，默认会以 <code>multipart/form-data</code> 格式上传文件（即二进制流方式），这与 Spring Boot 后端接口 <code>MultipartFile multipartFile</code> 参数是完全匹配的，不需要额外设置请求类型。</p>
<p>字段名需与后端参数名一致，如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;el-upload<br>  class=&quot;upload-demo&quot;<br>  action=&quot;http://localhost:8080/file/upload&quot;<br>  :on-preview=&quot;handlePreview&quot;<br>  :on-remove=&quot;handleRemove&quot;<br>  :file-list=&quot;fileList&quot;<br>  list-type=&quot;picture&quot;<br>  :headers=&quot;headers&quot;<br>  name=&quot;multipartFile&quot;<br>&gt;<br>          &lt;el-button size=&quot;small&quot; type=&quot;primary&quot;&gt;点击上传&lt;/el-button&gt;<br>        &lt;/el-upload&gt;<br></code></pre></td></tr></table></figure>

<p>特么的后端响应成功。</p>
<p><img src="http://blog.memory-life.xyz/image-20250426222734662.png" alt="image-20250426222734662"></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">2025-04-26 22:29:32.452  INFO 9200 --- [nio-8080-exec-1] com.macro.mall.common.log.WebLogAspect   : &#123;<span class="hljs-string">&quot;username&quot;</span>:<span class="hljs-string">&quot;admin&quot;</span>,<span class="hljs-string">&quot;startTime&quot;</span>:1745677633269,<span class="hljs-string">&quot;spendTime&quot;</span>:139182,<span class="hljs-string">&quot;basePath&quot;</span>:<span class="hljs-string">&quot;http://localhost:8080&quot;</span>,<span class="hljs-string">&quot;uri&quot;</span>:<span class="hljs-string">&quot;/file/upload&quot;</span>,<span class="hljs-string">&quot;url&quot;</span>:<span class="hljs-string">&quot;http://localhost:8080/file/upload&quot;</span>,<span class="hljs-string">&quot;method&quot;</span>:<span class="hljs-string">&quot;POST&quot;</span>,<span class="hljs-string">&quot;ip&quot;</span>:<span class="hljs-string">&quot;192.168.1.11&quot;</span>,<span class="hljs-string">&quot;result&quot;</span>:<span class="hljs-string">&quot;blog.memory-life.xyz/mall/35b1b8bb-fc6c-401e-87a1-d95eb0c6c3a8.jpeg&quot;</span>&#125;<br></code></pre></td></tr></table></figure>

<p>这个响应同下午使用 Postman 测试结果完全一致。</p>
<p>删除已上传的图片，上传前预览效果，待完善。目前还没有完成上传图片后插入数据库。</p>
<p>这个流程倒是合理，但目前后端商品管理非我实现，改动起来比较困难，暂不做改动，继续修改其他问题。</p>
<pre><code class=" mermaid">sequenceDiagram
    participant 前端
    participant 后端
    前端-&gt;&gt;后端: 1. 先创建商品（获取商品ID）
    后端--&gt;&gt;前端: 返回商品ID
    前端-&gt;&gt;后端: 2. 上传图片（携带商品ID）
    后端-&gt;&gt;数据库: 3. 保存图片并关联商品ID
</code></pre>

<p>图片上传成功或失败后的反馈。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;el-upload<br>  class=&quot;upload-demo&quot;<br>  action=&quot;http://localhost:8080/file/upload&quot;<br>  :on-preview=&quot;handlePreview&quot;<br>  :on-remove=&quot;handleRemove&quot;<br>  :file-list=&quot;fileList&quot;<br>  list-type=&quot;picture&quot;<br>  :headers=&quot;headers&quot;<br>  name=&quot;multipartFile&quot;<br>  :on-success=&quot;handleSuccess&quot;<br>  :on-error=&quot;handleError&quot;<br>&gt;<br>          &lt;el-button size=&quot;small&quot; type=&quot;primary&quot;&gt;点击上传&lt;/el-button&gt;<br>        &lt;/el-upload&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// 上传成功回调</span><br><span class="hljs-title function_">handleSuccess</span>(<span class="hljs-params">response, file, fileList</span>) &#123;<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;上传成功&quot;</span>, response);<br>  <span class="hljs-variable language_">this</span>.<span class="hljs-property">$message</span>.<span class="hljs-title function_">success</span>(<span class="hljs-string">&quot;上传成功&quot;</span>);<br>&#125;,<br><br><span class="hljs-comment">// 上传失败回调</span><br><span class="hljs-title function_">handleError</span>(<span class="hljs-params">err, file, fileList</span>) &#123;<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&quot;上传失败&quot;</span>, err);<br>  <span class="hljs-variable language_">this</span>.<span class="hljs-property">$message</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&quot;上传失败&quot;</span>);<br>&#125;,<br></code></pre></td></tr></table></figure>

<p>后端统一返回结果，便于解析。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@PostMapping(&quot;/upload&quot;)</span><br><span class="hljs-keyword">public</span> CommonResult&lt;String&gt; <span class="hljs-title function_">upload</span><span class="hljs-params">(MultipartFile multipartFile)</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>    <span class="hljs-type">String</span> <span class="hljs-variable">upload</span> <span class="hljs-operator">=</span> fileService.upload(multipartFile);<br>    <span class="hljs-keyword">return</span> CommonResult.success(upload);<br>&#125;<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/mahmud/p/16931006.html">ElementUI 实现图片上传的功能 🌈~（已完成 ✔） - Mahmud(مەھمۇد) - 博客园 (cnblogs.com)</a></p>
<p>明天再看吧，问题全部在前端，无聊。</p>
<h2 id="操作系统"><a href="#操作系统" class="headerlink" title="操作系统"></a>操作系统</h2><h2 id="网络编程"><a href="#网络编程" class="headerlink" title="网络编程"></a>网络编程</h2><blockquote>
<p>2025 年 4 月 9 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7109497228103778311">(二)Java 网络编程之爆肝 HTTP、HTTPS、TLS 协议及对称与非对称加密原理！作为一名程序员，尤其是作为一名后端 J - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7112826654291918855">(三)Nginx 一网打尽：动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化…想要的这都有！不论前端后端，如果你 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7116421978776404004">(四)网络编程之请求分发篇：负载均衡静态调度算法、平滑轮询加权、一致性哈希、最小活跃数算法实践！现如今所有的技术栈中，只 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7121990433084801061">(五)网络编程之流量接入层设计：基于性能怪兽从零构建日均亿级吞吐量的网关架构！如果你是前端，看完本文会让你认识到后端世界 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7124553120859815967">(六)网络编程之化身一个请求感受浏览器输入 URL 后奇妙的网络之旅！学技术太枯燥？本文带你如同看小说一样，化身一个网络请求 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7130952602350534693">(七)Java 网络编程-IO 模型篇之从 BIO、NIO、AIO 到内核 select、epoll 剖析！如若你对于面试要求中的“ - 掘金 (juejin.cn)</a></p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">BIO就是Java的传统IO模型，与其相关的实现都位于java.io包下，其通信原理是客户端、服务端之间通过Socket套接字建立管道连接，然后从管道中获取对应的输入<span class="hljs-regexp">/输出流，最后利用输入/</span>输出流对象实现发送/接收信息，案例如下：<br></code></pre></td></tr></table></figure>

<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs awk">观察如上结果，其实执行过程原理很简单：<br><br>①服务端启动后会执行accept()方法等待客户端连接到来。<br>②客户端启动后会通过IP及端口，与服务端通过Socket套接字建立连接。<br>③然后双方各自从套接字中获取输入<span class="hljs-regexp">/输出流，并通过流对象发送/</span>接收消息。<br></code></pre></td></tr></table></figure>

<figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs scss">①先创建对应类型的缓冲区<br>②通过put这类方法往缓冲区中写入数据<br>③调用<span class="hljs-built_in">flip</span>()方法将缓冲区转换为读模式<br>④通过get这类方法从缓冲区中读取数据<br>⑤调用<span class="hljs-attribute">clear</span>()、<span class="hljs-built_in">compact</span>()方法清空缓冲区数据<br></code></pre></td></tr></table></figure>

<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs mipsasm">在前面咱们详细叙述了Linux五种IO模型以及<span class="hljs-keyword">Java所提供的三种IO模型支持，对于Java-IO这块内容，阻塞、非阻塞、同步、异步等这些区别就不再聊了，认真看下来本文后自然会有答案，最后是需要重点表明一点：NIO、AIO都是单线程处理多个连接，但并不代表着说永远只有一条线程对网络连接进行处理，这里所谓的单线程处理多个连接，其实本质上是指单条线程接收客户端连接。</span><br><span class="hljs-keyword"></span>   从上述这段话中应该可以得知：<span class="hljs-keyword">Java-NIO、AIO本质上对于客户端的网络连接照样会启动多条线程处理，只不过与BIO的区别如下：</span><br><span class="hljs-keyword"></span><br><span class="hljs-keyword">Java-BIO：当客户端到来连接请求时，就会分配一条线程处理。</span><br><span class="hljs-keyword"></span><span class="hljs-keyword">Java-NIO：客户端的连接请求会先注册到选择器上，选择器轮询到有事件触发时，才会分配一条线程处理。</span><br><span class="hljs-keyword"></span><span class="hljs-keyword">Java-AIO：客户端的连接到来后同样会先注册到选择器上，但客户端的I/O请求会先交由OS处理，当内核将数据拷贝完成后才会分配一条线程处理。</span><br><span class="hljs-keyword"></span><br><span class="hljs-keyword">Java-BIO、NIO、AIO本质上都会为一个请求分配一条线程处理，但核心区别在于启动的时机不同，当然，如果非要用一条线程处理多个客户端连接的所有工作也并非不行，但这样会造成系统极为低效，例如1000个文件下载的请求到来，全都交由选择器上监听客户端连接的那条线程处理，其效率诸位可想而知。</span><br><span class="hljs-keyword"></span>最后多叨叨一句，其实<span class="hljs-keyword">Java-NIO、AIO方面的设计，无论是从使用简洁度而言，还是从源码的可观性而言，其实都并不算理想，如若有小伙伴阅读过JUC包的源码，再回来对比NIO包的源码，两者差别甚大，所以本质上在之后的过程中，如若要用到Java-NIO、AIO方面的技术，一般都会采用Netty框架实现，Netty这个网络通信框架则对nio包提供的原生IO-API进一步做了封装，也解决了NIO包下原生API存在的诸多问题，因此在后续的文章中也会重点分析Netty这个框架。</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7136110312440201223">(八)Java 网络编程之 IO 模型篇-内核 Select、Poll、Epoll 多路复用函数源码深度历险！相信你一定听说过 se - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7176869085521641509#heading-31">(九)Java 网络编程无冕之王-这回把大名鼎鼎的 Netty 框架一网打尽！现如今分布式/微服务大行其道，而其根基在于网络编 - 掘金 (juejin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://juejin.cn/post/7264414580774928443#heading-17">(十二)探索高性能通信与 RPC 框架基石：Json、ProtoBuf、Hessian 序列化详解如今这个分布式风靡的时代，网 - 掘金 (juejin.cn)</a></p>
<h2 id="SpringCloud"><a href="#SpringCloud" class="headerlink" title="SpringCloud"></a>SpringCloud</h2><h2 id="Elasticsearch"><a href="#Elasticsearch" class="headerlink" title="Elasticsearch"></a>Elasticsearch</h2><h2 id="电磁波"><a href="#电磁波" class="headerlink" title="电磁波"></a>电磁波</h2><blockquote>
<p>2025 年 7 月 30 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1833615256102928190&wfr=spider&for=pc">理性看待WIFI辐射及其安全影响</a></p>
<p>简而言之，<strong>WIFI技术利用特定频率的电磁波进行无线通信</strong>。电磁波按照波长和频率的不同，被划分为无线电波、微波、红外线、可见光、紫外线、X射线以及γ射线等众多类型</p>
<p>日常生活中，我们接触到的<strong>WIFI、手机和雷达等设备所产生的辐射，大多属于非电离辐射</strong>。特别是WIFI，其产生的超短波电场辐射强度，只要<strong>低于12V/m（即141.6dBμV/m），便被视为安全范围</strong>。实际上，根据相关调查，目前市场上主流路由器的最大辐射强度远低于这一国家标准。</p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/lsdb/p/10157355.html">电磁波、无线电、802、WLAN及WiFi的区别与联系 - 诸子流 - 博客园</a></p>
<p><a target="_blank" rel="noopener" href="https://www.zhihu.com/question/1905008545885294725/answer/1916961329555694696">(31 封私信 / 17 条消息) WIFI和WLAN的区别和关联是什么？ - 知乎</a></p>
<p>为什么“光也是一种电磁波”? - 糊涂人的回答 - 知乎<br><a target="_blank" rel="noopener" href="https://www.zhihu.com/question/11820976346/answer/1905609806770860910">https://www.zhihu.com/question/11820976346/answer/1905609806770860910</a></p>
<p>光既有特定波长也有特定频率，波长是指波动在一个周期内传播的距离，在波动传播的过程中，相邻两个相同相位点之间的距离就是一个波长。频率主要描述的是单位时间内周期性变化的次数，是描述周期运动频繁程度的量，它是物质在1秒内完成周期性变化的次数。为了纪念德国物理学家赫兹的贡献，人们将频率的单位命名为赫兹，简称“赫”，符号为Hz。光的频率就是光波在单位时间内重复的次数，单位是赫兹，也就是每秒振动的次数。</p>
<p>由于波速等于波长与频率的乘积，表示波动在单位时间内传播的距离。可知波长和频率是成反比的，也就是说，频率越高，波长越短；频率越低，波长越长。</p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1794127193390203366&wfr=spider&for=pc">为了孩子，应知常识——光</a></p>
<h2 id="NVIDIA"><a href="#NVIDIA" class="headerlink" title="NVIDIA"></a>NVIDIA</h2><blockquote>
<p>2025 年 7 月 30 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/378199281">(31 封私信 / 19 条消息) 快速回顾NVIDIA显卡发展史，看看小伙伴们都用过哪些显卡。 - 知乎</a></p>
<p>显卡知识科普大全：通俗易懂的显卡知识扫盲与显卡型号参数详解 - 艺品志的文章 - 知乎<br><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/680714577">https://zhuanlan.zhihu.com/p/680714577</a></p>
<p>Nvidia显卡的发展历史阶段及特点 - 红尘的文章 - 知乎<br><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/710616598">https://zhuanlan.zhihu.com/p/710616598</a></p>
<p><a target="_blank" rel="noopener" href="https://www.zhihu.com/collection/973895256">(31 封私信 / 19 条消息) 电脑配置 - 收藏夹 - 知乎</a></p>
<p><a target="_blank" rel="noopener" href="https://www.zhihu.com/people/meng-de-er-de-xiao-wan-dou-28/columns">(31 封私信 / 19 条消息) 开关芝士 - 知乎</a></p>
<p><a target="_blank" rel="noopener" href="https://www.crucial.cn/content/crucial/zh/home/articles/about-ssd/m2-vs-pcie.html">M.2固态硬盘接口，M.2与PCI-E的区别 |Crucial(英睿达) | Crucial 英睿达</a></p>
<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/137680552">(31 封私信 / 19 条消息) 【电脑DIY】从萌新入门到开窍——硬盘篇 - 知乎</a></p>
<blockquote>
<p>2025 年 8 月 2 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.mydrivers.com/zhuanti/tianti/gpum/index.html">笔记本显卡性能天梯图</a></p>
<p><a target="_blank" rel="noopener" href="https://www.365pcbuy.com/article-398.html">极速空间显卡天梯图 （2025台式显卡和笔记本显卡性能排行）——跟小虫学电脑配置_显卡_硬件知识_极速空间-专业电脑配置研究网站</a></p>
<blockquote>
<p>2025 年 8 月 10 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://post.smzdm.com/talk/p/akk9nwm4/">不懂英伟达显卡命名的小白可以来了解一下_什么值得买</a></p>
<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mipsasm">Giga Texel <span class="hljs-keyword">Shader </span><span class="hljs-keyword">eXtreme（超级纹理像素着色器）</span><br></code></pre></td></tr></table></figure>

<p>[百度翻译_领先的AI大模型翻译_支持文本/文档/图片翻译](<a target="_blank" rel="noopener" href="https://fanyi.baidu.com/mtpe-individual/transText?query=Giga">https://fanyi.baidu.com/mtpe-individual/transText?query=Giga</a> Texel Shader eXtreme&amp;lang=en2zh&amp;ext_channel=Aldtype)</p>
<p><a target="_blank" rel="noopener" href="https://www.zhihu.com/tardis/zm/art/494370542?source_id=1005">被遗忘的HEDT平台！少数派攒机方案，有专业需求的可以上</a></p>
<p><a target="_blank" rel="noopener" href="https://www.zhihu.com/question/329308486/answer/1915034467468305224">(55 封私信 / 84 条消息) hedt平台究竟是什么？ - 知乎</a></p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs makefile">HEDT 高端台式机定义?<br><span class="hljs-section">高端台式机指的是性能远超主流水平的台式计算机，通常配备顶级硬件:高核心数和高频率的CPU、卓越的图形和计算性能的GPU、大容量内存、超高速存储、先进散热系统和稳健供电。</span><br>这些系统在游戏、内容制作、科学计算以及AI领域拥有广泛优势。<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.shopify.com/zh/blog/what-is-a-sku-number">什么是SKU编号？如何在零售中使用SKU编号？（2025） - Shopify 中国</a></p>
<p><a target="_blank" rel="noopener" href="https://www.zhihu.com/column/c_1238473669946200064">(55 封私信 / 84 条消息) 萌新必看——小白快乐的电脑DIY科普 - 知乎</a></p>
<h2 id="比特币"><a href="#比特币" class="headerlink" title="比特币"></a>比特币</h2><blockquote>
<p>2025 年 10 月 29 日</p>
</blockquote>
<p>比特币不是央行发行的法定货币（比如人民币、美元），而是 2009 年诞生的 “去中心化数字资产”—— 没有任何机构（银行、政府）能控制它，靠全球数百万台电脑组成的网络维护。你可以把它理解成 “数字世界的限量版藏品”，总量固定 2100 万枚（2025 年已挖出约 1950 万枚），挖完后不再新增，这也是它价格波动的核心原因之一。</p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1844035024775868520&wfr=spider&for=pc">比特币到底怎么“挖”的？机器人+矿场背后的秘密，几分钟教你看懂！</a></p>
<p>比特币挖矿并非物理挖矿，而是用超强计算机一起“解数学难题”。矿工们在全世界搭建矿机（ASIC矿机、显卡矿机），不断做 SHA‐256 哈希运算，谁先找到符合条件的哈希值，谁就能把一个区块加入区块链，拿到比特币奖励 + 手续费。</p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1842588585500459150&wfr=spider&for=pc">2025 年还不懂比特币？通俗解析：它不是 “网上的钱”，3 个关键点 + 避坑指南</a></p>
<p><a target="_blank" rel="noopener" href="https://bitcoin.org/zh_CN/faq">常见问题 - 比特币</a></p>
<p><a target="_blank" rel="noopener" href="https://www.jb51.net/blockchain/1000672.html">什么是比特币挖矿？如何挖矿及风险介绍_比特币_区块链_脚本之家</a></p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1842049363783237351&wfr=spider&for=pc">听不懂区块链术语？用大白话讲透核心逻辑，避免被忽悠</a></p>
<p><a target="_blank" rel="noopener" href="https://www.zhihu.com/question/37290469/answer/3044442425">(93 封私信 / 82 条消息) 区块链是什么，如何简单易懂地介绍区块链？ - 知乎</a></p>
<h2 id="时区"><a href="#时区" class="headerlink" title="时区"></a>时区</h2><blockquote>
<p>2025 年 10 月 29 日</p>
</blockquote>
<p>美国地跨西五区至西十区，共计六个时区，每个时区都有其特定的标准时间。</p>
<p>从东向西排列，这些时区依次为东部时间（EST，对应西五区）、中部时间（CST，西六区）、山地时间（MST，西七区）、太平洋时间（PST，西八区）、阿拉斯加时间（AKST，西九区）以及夏威夷时间（HST，西十区）。</p>
<p><a target="_blank" rel="noopener" href="https://baijiahao.baidu.com/s?id=1836543767353355015&wfr=spider&for=pc">解析美国时区：从历史到时差转换的全方位解读</a></p>
<p>百度直接搜索某个城市时间，基本都能在检索结果第一栏很方便就能看到答案。</p>
<p>从东到西依次将当地时间转换为北京时间，需分别增加十三小时（东部时间）、十四小时（中部时间）、十五小时（山地时间）、十六小时（山地时间）、十七小时（阿拉斯加时间）和十八小时（夏威夷时间）。</p>
<p><a target="_blank" rel="noopener" href="https://mbd.baidu.com/newspage/data/dtlandingsuper?nid=dt_4883803452188297012&sourceFrom=search_a">美国6大时区全解析，旅行必备</a></p>
<h2 id="软考"><a href="#软考" class="headerlink" title="软考"></a>软考</h2><blockquote>
<p>2025 年 11 月 7 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.ruankao.org.cn/article/content/2502121040396048212475606.html">中国计算机技术职业资格网</a></p>
<p><a target="_blank" rel="noopener" href="https://www.educity.cn/">希赛网_专注在线职业教育24年</a></p>
<p>明年上半年可以考<strong>信息系统项目管理师</strong>高项，明年下半年可以考<strong>系统架构设计师</strong>高项，计划用一年的时间拿下两本软考高级证书。</p>
<p>中级暂不考虑，已经有<strong>软件设计师</strong>中项了，</p>
<p><a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E7%A7%AF%E5%88%86%E5%85%A5%E6%88%B7/6306472">积分入户_百度百科</a></p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs">积分入户是中国部分城市基于积分指标体系审核外来务工人员落户资格的户籍管理政策。<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/1924035980509287457">(99+ 封私信 / 82 条消息) 信息系统项目管理师证书（高项）有什么用？ - 知乎</a></p>
<h1 id="补全计划"><a href="#补全计划" class="headerlink" title="补全计划"></a>补全计划</h1><h2 id="广度"><a href="#广度" class="headerlink" title="广度"></a>广度</h2><blockquote>
<p>2025 年 4 月 16 日</p>
</blockquote>
<p>[Java IO 流详解：字节流、字符流与缓冲流的使用-CSDN 博客](<a target="_blank" rel="noopener" href="https://blog.csdn.net/Lee0620/article/details/121261869?ops_request_misc=%7B%22request_id%22:%22e0787ebc62c941e678443b45683c74ab%22,%22scm%22:%2220140713.130102334..%22%7D&amp;request_id=e0787ebc62c941e678443b45683c74ab&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-121261869-null-null.142%5Ev102%5Econtrol&amp;utm_term=Java">https://blog.csdn.net/Lee0620/article/details/121261869?ops_request_misc=%7B%22request%5Fid%22%3A%22e0787ebc62c941e678443b45683c74ab%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&amp;request_id=e0787ebc62c941e678443b45683c74ab&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-121261869-null-null.142^v102^control&amp;utm_term=Java</a> IO&amp;spm=1018.2226.3001.4187)</p>
<p>[【Java】I/O 操作详解_java io 操作-CSDN 博客](<a target="_blank" rel="noopener" href="https://blog.csdn.net/island1314/article/details/142895276?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=Java">https://blog.csdn.net/island1314/article/details/142895276?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=Java</a> IO&amp;utm_medium=distribute.pc_search_result.none-task-blog-2<del>all</del>sobaiduweb~default-2-142895276.142^v102^control&amp;spm=1018.2226.3001.4187)</p>
<p>[Java 多线程（超详细！）_java 多线程-CSDN 博客](<a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_44715943/article/details/116714584?ops_request_misc=%7B%22request_id%22:%2221af9c03f92010ed8e3c42eb929a6ed5%22,%22scm%22:%2220140713.130102334..%22%7D&amp;request_id=21af9c03f92010ed8e3c42eb929a6ed5&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-116714584-null-null.142%5Ev102%5Econtrol&amp;utm_term=Java">https://blog.csdn.net/qq_44715943/article/details/116714584?ops_request_misc=%7B%22request%5Fid%22%3A%2221af9c03f92010ed8e3c42eb929a6ed5%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&amp;request_id=21af9c03f92010ed8e3c42eb929a6ed5&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-116714584-null-null.142^v102^control&amp;utm_term=Java</a> 多线程&amp;spm=1018.2226.3001.4187)</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/ThinkWon/article/details/98844796?ops_request_misc=%7B%22request_id%22:%22d3245d041a76c7195f94fdc7feb12979%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=d3245d041a76c7195f94fdc7feb12979&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-98844796-null-null.142%5Ev102%5Econtrol&utm_term=Java%E9%9B%86%E5%90%88&spm=1018.2226.3001.4187">Java 集合框架详解-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_44715943/article/details/120587716">Java 反射机制详解及应用-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_45395059/article/details/126006369?ops_request_misc=%7B%22request_id%22:%22841e82b77cfd0c25b488facce243c33c%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=841e82b77cfd0c25b488facce243c33c&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-126006369-null-null.142%5Ev102%5Econtrol&utm_term=Java%E6%B3%9B%E5%9E%8B&spm=1018.2226.3001.4187">Java 中的泛型（两万字超全详解）_java 泛型-CSDN 博客</a></p>
<blockquote>
<p>2025 年 4 月 17 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_45559559/article/details/136726238?ops_request_misc=%7B%22request_id%22:%222e98795426521b733d2cfda996bc00c7%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=2e98795426521b733d2cfda996bc00c7&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-2-136726238-null-null.142%5Ev102%5Econtrol&utm_term=Spring&spm=1018.2226.3001.4187">Spring &amp; SpringBoot（详解）-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/vcj1009784814/article/details/106391982?spm=1001.2014.3001.5506">mybatis 看这一篇就够了，简单全面一发入魂_mybatis 一发入魂-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/vcj1009784814/article/details/115159687">Mybatis Plus 看这篇就够了，通俗易懂，一发入魂_com.baomidou.mybatisplus.core.mybatismapperannotat-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/vcj1009784814/article/details/115159687">Mybatis Plus 看这篇就够了，通俗易懂，一发入魂_com.baomidou.mybatisplus.core.mybatismapperannotat-CSDN 博客</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/vcj1009784814/article/details/121931026">RabbitMQ 学习笔记（持续更新 ing）_setprefetchcount-CSDN 博客</a></p>
<p>[00 开篇词 从零开始：为什么要学习 Spring Boot？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/00 开篇词 从零开始：为什么要学习 Spring Boot？.md)</p>
<blockquote>
<p>2025 年 4 月 18 日</p>
</blockquote>
<p>[01 家族生态：如何正确理解 Spring 家族的技术体系？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/01 家族生态：如何正确理解 Spring 家族的技术体系？.md)</p>
<p>[02 案例驱动：如何剖析一个 Spring Web 应用程序？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/02 案例驱动：如何剖析一个 Spring Web 应用程序？.md)</p>
<p>[03 多维配置：如何使用 Spring Boot 中的配置体系？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/03 多维配置：如何使用 Spring Boot 中的配置体系？.md)</p>
<p>[04 定制配置：如何创建和管理自定义的配置信息？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/04 定制配置：如何创建和管理自定义的配置信息？.md)</p>
<p>[05 自动配置：如何正确理解 Spring Boot 自动配置实现原理？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/05 自动配置：如何正确理解 Spring Boot 自动配置实现原理？.md)</p>
<p>[06 基础规范：如何理解 JDBC 关系型数据库访问规范？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/06 基础规范：如何理解 JDBC 关系型数据库访问规范？.md)</p>
<p>[07 数据访问：如何使用 JdbcTemplate 访问关系型数据库？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/07 数据访问：如何使用 JdbcTemplate 访问关系型数据库？.md)</p>
<p>[08 数据访问：如何剖析 JdbcTemplate 数据访问实现原理？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/08 数据访问：如何剖析 JdbcTemplate 数据访问实现原理？.md)</p>
<p>[10 ORM 集成：如何使用 Spring Data JPA 访问关系型数据库？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/10 ORM 集成：如何使用 Spring Data JPA 访问关系型数据库？.md)</p>
<p>[17 安全架构：如何理解 Spring 安全体系的整体架构？ (lianglianglee.com)](<a target="_blank" rel="noopener" href="https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/Spring">https://learn.lianglianglee.com/专栏/Spring</a> Boot 实战开发/17 安全架构：如何理解 Spring 安全体系的整体架构？.md)</p>
<h2 id="Spring-AI"><a href="#Spring-AI" class="headerlink" title="Spring AI"></a>Spring AI</h2><blockquote>
<p>2025 年 6 月 4 日</p>
</blockquote>
<p>[Spring AI 框架：从零开始掌握 AI 与 Spring 的完美结合！_spring-ai-CSDN 博客](<a target="_blank" rel="noopener" href="https://blog.csdn.net/2301_78858041/article/details/146076432?ops_request_misc=%7B%22request_id%22:%22ff4123b3aa4b8995308234e612da553a%22,%22scm%22:%2220140713.130102334..%22%7D&amp;request_id=ff4123b3aa4b8995308234e612da553a&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-2-146076432-null-null.142%5Ev102%5Econtrol&amp;utm_term=Spring">https://blog.csdn.net/2301_78858041/article/details/146076432?ops_request_misc=%7B%22request%5Fid%22%3A%22ff4123b3aa4b8995308234e612da553a%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&amp;request_id=ff4123b3aa4b8995308234e612da553a&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-2-146076432-null-null.142^v102^control&amp;utm_term=Spring</a> AI&amp;spm=1018.2226.3001.4187)</p>
<p>[Spring AI: 为 Java 应用赋能人工智能_spring ai java-CSDN 博客](<a target="_blank" rel="noopener" href="https://blog.csdn.net/jgk666666/article/details/147569814?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=Spring">https://blog.csdn.net/jgk666666/article/details/147569814?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=Spring</a> AI&amp;utm_medium=distribute.pc_search_result.none-task-blog-2<del>all</del>sobaiduweb~default-0-147569814.142^v102^control&amp;spm=1018.2226.3001.4187)</p>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/course/1915010091721236482/section/1915011476122574850?type=#heading-0">1 - 项目总览 - AI 超级智能体项目教程 - 编程导航教程 (codefather.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://www.codefather.cn/course/1907378983347892226/section/1907379564201353218#heading-12">AI 编程技术 - 程序员鱼皮 AI 指南 - 编程导航教程 (codefather.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://ai.codefather.cn/#%E7%B2%BE%E9%80%89%E8%B5%84%E6%BA%90">欢迎来到 鱼皮的 AI 知识库！ | 鱼皮 AI 知识库 (codefather.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/liyupi/ai-guide">liyupi/ai-guide: 程序员鱼皮的 AI 知识库，汇总热门的 AI 大模型和工具，比如 Deepseek 使用指南、提示词技巧、知识干货、应用场景、AI 变现、行业资讯、教程资源等一系列内容，帮助你快速掌握 AI 技术，走在时代前沿。涉及的大模型 ChatGPT、Claude、Gemini、Deepseek、Deepseek-r1、QWEN、GROK 等 (github.com)</a></p>
<h2 id="开源"><a href="#开源" class="headerlink" title="开源"></a>开源</h2><blockquote>
<p>2025 年 7 月 1 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://chencoding.top:8090/#/README?id=%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7">优秀的开源项目 - Java 陈序员 (chencoding.top)</a></p>
<p><a target="_blank" rel="noopener" href="https://w2.xenex.world/?key=j0d41c3322mb211xkcye&visitor_id=963937632257581239&cost=0.005000&zoneid=9382406&campaignid=9064793&device=&browser=edge&os=windows&osversion=win10&country=CN&language=zh&isp=china+unicom+shanxi+province+network&user_activity=low&banner=22975278&zone_type=in-page-push">R-VPN - 在中国以最大速度畅享自由互联网 (xenex.world)</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/Alvin9999/new-pac/tree/master">Alvin9999/new-pac: 翻墙-科学上网、自由上网、免费科学上网、免费翻墙、fanqiang、油管 youtube/视频下载、软件、VPN、一键翻墙浏览器，vps 一键搭建翻墙服务器脚本/教程，免费 shadowsocks/ss/ssr/v2ray/goflyway 账号/节点，翻墙梯子，电脑、手机、iOS、安卓、windows、Mac、Linux、路由器翻墙、科学上网、youtube 视频下载、youtube 油管镜像/免翻墙网站、美区 apple id 共享账号、翻墙-科学上网-梯子 (github.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://pdf2md.morethan.io/">PDF to Markdown (morethan.io)</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/Anduin2017/HowToCook/tree/master">Anduin2017/HowToCook: 程序员在家做饭方法指南。Programmer’s guide about how to cook at home (Simplified Chinese only). (github.com)</a></p>
<p>程序员做饭指南，这个开源项目有意思。</p>
<p><a target="_blank" rel="noopener" href="https://cook.aiursoft.cn/">How To Cook (aiursoft.cn)</a></p>
<p>如果需要在本地部署菜谱 Web 服务，可以在安装 Docker 后运行下面命令：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs awk">docker pull ghcr.io<span class="hljs-regexp">/anduin2017/</span>how-to-cook:latest<br>docker run -d -p <span class="hljs-number">5000</span>:<span class="hljs-number">80</span> ghcr.io<span class="hljs-regexp">/anduin2017/</span>how-to-cook:latest<br></code></pre></td></tr></table></figure>

<p>如需下载 PDF 版本，可以在浏览器中访问 <a target="_blank" rel="noopener" href="https://cook.aiursoft.cn/document.pdf">/document.pdf</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/shengxinjing/programmer-job-blacklist">shengxinjing/programmer-job-blacklist: :see_no_evil:程序员找工作黑名单，换工作和当技术合伙人需谨慎啊 更新有赞 (github.com)</a></p>
<blockquote>
<p>2025 年 7 月 2 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://nageoffer.com/12306/">什么是 12306 铁路购票？ | 拿个 offer-开源&amp;项目实战 (nageoffer.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/NanmiCoder/MediaCrawler">NanmiCoder/MediaCrawler: 小红书笔记 | 评论爬虫、抖音视频 | 评论爬虫、快手视频 | 评论爬虫、B 站视频 ｜ 评论爬虫、微博帖子 ｜ 评论爬虫、百度贴吧帖子 ｜ 百度贴吧评论回复爬虫 | 知乎问答文章｜评论爬虫 (github.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/fluid-dev/hexo-theme-fluid">fluid-dev/hexo-theme-fluid: :ocean: 一款 Material Design 风格的 Hexo 主题 / An elegant Material-Design theme for Hexo (github.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://demo.halo.run/categories/halo">demo.halo.run/categories/halo</a></p>
<p>微信小程序。</p>
<p><a target="_blank" rel="noopener" href="https://github.com/sav7ng/WeHalo">sav7ng/WeHalo: WeHalo 简约风 的微信小程序版博客:sparkles: (github.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://www.minapper.com/">微慕 wordpress 小程序 - (minapper.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://gitee.com/iamxjb/rest-api-to-miniprogram">WordpPress 小程序插件端: REST API TO MiniProgram ——WordpPress rest api 定制化插件，帮助站长快速生成 wordpress 小程序。 (gitee.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://github.com/ryanuo/hexo-wx-api">ryanuo/hexo-wx-api: A WeChat applet based on the hexo framework (github.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://demo.waf-ce.chaitin.cn:9443/statistics">雷池 WAF (chaitin.cn)</a></p>
<p><a target="_blank" rel="noopener" href="https://geeeeeeeek.github.io/web_tool/#friendlink">Web Tool - 网址导航 (geeeeeeeek.github.io)</a></p>
<p><a target="_blank" rel="noopener" href="https://gitee.com/cryfeifei/WeHexo">WeHexo: Hexo 微信小程序版本 (gitee.com)</a></p>
<p>这里有几个开源的 Hexo 微信小程序。</p>
<p><a target="_blank" rel="noopener" href="https://github.com/CryFeiFei/WeHexo">CryFeiFei/WeHexo: 微信小程序 hexo 版本 (github.com)</a></p>
<p><a target="_blank" rel="noopener" href="https://hunterx.xyz/try-wehexo.html">尝试 Hexo 转小程序 | 猎人杂货铺 (hunterx.xyz)</a></p>
<p>从快速实现一个页面开始，逐步进行优化，姑且将这当作是巩固小程序开发经验的契机吧。</p>
<h1 id="重塑计划"><a href="#重塑计划" class="headerlink" title="重塑计划"></a>重塑计划</h1><blockquote>
<p>2025 年 7 月 21 日</p>
</blockquote>
<p>上周重装了电脑，之前设置过的环境变量全部清除了，趁此机会从零开始按需挨个重装一遍。</p>
<p><a target="_blank" rel="noopener" href="https://dev.mysql.com/downloads/windows/installer/">MySQL :: Download MySQL Installer</a></p>
<p><a target="_blank" rel="noopener" href="https://cloud.tencent.com/developer/article/2093568">MySQL安装配置教程（超级详细、保姆级）-腾讯云开发者社区-腾讯云</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">mysqld -–initialize-insecure<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">mysqld -install<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">mysql -u root -p密码<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">mysql&gt; quit<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">net stop mysql<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_74825614/article/details/146432852">Windows安装Redis图文教程_windows下redis安装步骤-CSDN博客</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">redis-server.exe<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">redis-server redis.windows.conf <br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">redis-server.exe --service-install redis.windows-service.conf --service-name RedisServiceName<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash">127.0.0.1:6379&gt; ping<br>PONG<br>127.0.0.1:6379&gt; <span class="hljs-built_in">set</span> good:name fuck<br>OK<br>127.0.0.1:6379&gt; get good:name<br><span class="hljs-string">&quot;fuck&quot;</span><br>127.0.0.1:6379&gt; get name:good<br><span class="hljs-string">&quot;fuck&quot;</span><br>127.0.0.1:6379&gt;<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_41918107/article/details/148554589">NVM 安装及配置教程（Windows）【安装】-CSDN博客</a></p>
<figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs applescript">nvm <span class="hljs-built_in">version</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_41823313/article/details/147190739">运行nvm list报错ERROR open \settings.txt: The system cannot find the file specified.-CSDN博客</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">C:\WINDOWS\system32&gt;nvm list<br><br>  * 18.16.1 (Currently using 64-bit executable)<br>    16.19.0<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs bash">C:\WINDOWS\system32&gt;nvm list available<br><br>|   CURRENT    |     LTS      |  OLD STABLE  | OLD UNSTABLE |<br>|--------------|--------------|--------------|--------------|<br>|    24.4.1    |   22.17.1    |   0.12.18    |   0.11.16    |<br>|    24.4.0    |   22.17.0    |   0.12.17    |   0.11.15    |<br>|    24.3.0    |   22.16.0    |   0.12.16    |   0.11.14    |<br>|    24.2.0    |   22.15.1    |   0.12.15    |   0.11.13    |<br>|    24.1.0    |   22.15.0    |   0.12.14    |   0.11.12    |<br>|    24.0.2    |   22.14.0    |   0.12.13    |   0.11.11    |<br>|    24.0.1    |   22.13.1    |   0.12.12    |   0.11.10    |<br>|    24.0.0    |   22.13.0    |   0.12.11    |    0.11.9    |<br>|   23.11.1    |   22.12.0    |   0.12.10    |    0.11.8    |<br>|   23.11.0    |   22.11.0    |    0.12.9    |    0.11.7    |<br>|   23.10.0    |   20.19.4    |    0.12.8    |    0.11.6    |<br>|    23.9.0    |   20.19.3    |    0.12.7    |    0.11.5    |<br>|    23.8.0    |   20.19.2    |    0.12.6    |    0.11.4    |<br>|    23.7.0    |   20.19.1    |    0.12.5    |    0.11.3    |<br>|    23.6.1    |   20.19.0    |    0.12.4    |    0.11.2    |<br>|    23.6.0    |   20.18.3    |    0.12.3    |    0.11.1    |<br>|    23.5.0    |   20.18.2    |    0.12.2    |    0.11.0    |<br>|    23.4.0    |   20.18.1    |    0.12.1    |    0.9.12    |<br>|    23.3.0    |   20.18.0    |    0.12.0    |    0.9.11    |<br>|    23.2.0    |   20.17.0    |   0.10.48    |    0.9.10    |<br><br>This is a partial list. For a complete list, visit https://nodejs.org/en/download/releases<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">nvm install 16.19.0<br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/zuodingquan666/article/details/142147104">Hexo框架学习——从安装到配置-CSDN博客</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs bash">D:\Blog\blog&gt;npm install -g hexo-cli<br><br>added 53 packages <span class="hljs-keyword">in</span> 16s<br><br>14 packages are looking <span class="hljs-keyword">for</span> funding<br>  run `npm fund` <span class="hljs-keyword">for</span> details<br>npm notice<br>npm notice New major version of npm available! 9.5.1 -&gt; 11.4.2<br>npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.4.2<br>npm notice Run npm install -g npm@11.4.2 to update!<br>npm notice<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install -g hexo-cli<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm uninstall -g hexo-cli<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm config get prefix<br></code></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">问题</th>
<th align="center">解决方案</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>&#39;hexo&#39; 不是内部或外部命令</code></td>
<td align="center">确保 <code>npm</code> 路径（如 <code>C:\Users\用户名\AppData\Roaming\npm</code>）已添加到 <code>PATH</code></td>
</tr>
<tr>
<td align="center"><code>npm</code> 路径找不到</td>
<td align="center">运行 <code>npm config get prefix</code> 查找路径</td>
</tr>
<tr>
<td align="center">修改 <code>PATH</code> 后仍无效</td>
<td align="center">重新安装 Hexo，或检查 Node.js 安装</td>
</tr>
</tbody></table>
<p>添加环境改变量：</p>
<figure class="highlight taggerscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs taggerscript">D:\softWare<span class="hljs-symbol">\n</span>vm<span class="hljs-symbol">\n</span>vm\v18.16.1<span class="hljs-symbol">\n</span>ode_global<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs bash">C:\WINDOWS\system32&gt;hexo -v<br>hexo-cli: 4.3.2<br>os: win32 10.0.19045 undefined<br>node: 16.19.0<br>v8: 9.4.146.26-node.24<br>uv: 1.43.0<br>zlib: 1.2.11<br>brotli: 1.0.9<br>ares: 1.18.1<br>modules: 93<br>nghttp2: 1.47.0<br>napi: 8<br>llhttp: 6.0.10<br>openssl: 1.1.1s+quic<br>cldr: 41.0<br>icu: 71.1<br>tz: 2022f<br>unicode: 14.0<br>ngtcp2: 0.8.1<br>nghttp3: 0.7.0<br></code></pre></td></tr></table></figure>

<blockquote>
<p>2025 年 7 月 22 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_47054648/article/details/125797571">JDK1.8下载、安装和配置环境-CSDN博客</a></p>
<p><a target="_blank" rel="noopener" href="https://www.oracle.com/cn/java/technologies/downloads/#java8-windows">Java Downloads | Oracle 中国</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250722105914085.png" alt="image-20250722105914085"></p>
<p>一键安装完成。</p>
<p><a target="_blank" rel="noopener" href="https://www.oracle.com/downloads/">Software Download | Oracle</a></p>
<p><a target="_blank" rel="noopener" href="https://www.jetbrains.com/zh-cn/">JetBrains: 软件开发者和团队的必备工具</a></p>
<h1 id="Node服务端"><a href="#Node服务端" class="headerlink" title="Node服务端"></a>Node服务端</h1><blockquote>
<p>2025 年 9 月 22 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.runoob.com/nodejs/nodejs-http-server.html">Node.js 创建第一个应用 | 菜鸟教程</a></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">var</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;http&#x27;</span>);<br><br>http.<span class="hljs-title function_">createServer</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">request, response</span>) &#123;<br><br>        <span class="hljs-comment">// 发送 HTTP 头部 </span><br>        <span class="hljs-comment">// HTTP 状态值: 200 : OK</span><br>        <span class="hljs-comment">// 内容类型: text/plain</span><br>        response.<span class="hljs-title function_">writeHead</span>(<span class="hljs-number">200</span>, &#123;<span class="hljs-string">&#x27;Content-Type&#x27;</span>: <span class="hljs-string">&#x27;text/plain&#x27;</span>&#125;);<br><br>        <span class="hljs-comment">// 发送响应数据 &quot;Hello World&quot;</span><br>        response.<span class="hljs-title function_">end</span>(<span class="hljs-string">&#x27;Hello World\n&#x27;</span>);<br>&#125;).<span class="hljs-title function_">listen</span>(<span class="hljs-number">8888</span>);<br><br><span class="hljs-comment">// 终端打印如下信息</span><br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;Server running at http://127.0.0.1:8888/&#x27;</span>);<br></code></pre></td></tr></table></figure>

<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">PS D:\Project\<span class="hljs-keyword">node</span><span class="hljs-title">\first0922</span>&gt; <span class="hljs-keyword">node</span> <span class="hljs-title">.\server</span>.js<br>Server running at http://<span class="hljs-number">127.0</span>.<span class="hljs-number">0.1</span>:<span class="hljs-number">8888</span>/<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20250922221911925.png" alt="image-20250922221911925"></p>
<p><a target="_blank" rel="noopener" href="https://www.runoob.com/nodejs/nodejs-buffer.html">Node.js Buffer(缓冲区) | 菜鸟教程</a></p>
<h1 id="Bootstrap"><a href="#Bootstrap" class="headerlink" title="Bootstrap"></a>Bootstrap</h1><blockquote>
<p>2025 年 9 月 23 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://www.runoob.com/bootstrap5/bootstrap5-install.html">Bootstrap5 安装使用 | 菜鸟教程</a></p>
<p><strong>下载 Bootstrap 5</strong></p>
<p>你可以去官网 <a target="_blank" rel="noopener" href="https://getbootstrap.com/">https://getbootstrap.com/</a> 下载 Bootstrap5 资源库。</p>
<p><strong>注：</strong>此外你还可以通过包的管理工具 npm、 yarn、gem、 composer 等来安装：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install bootstrap<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yarn add bootstrap<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">gem install bootstrap -v 5.1.1<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">composer require twbs/bootstrap:5.1.1<br></code></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Bootstrap5 实例<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;utf-8&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;viewport&quot;</span> <span class="hljs-attr">content</span>=<span class="hljs-string">&quot;width=device-width, initial-scale=1&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">link</span></span><br><span class="hljs-tag">      <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.1/css/bootstrap.min.css&quot;</span></span><br><span class="hljs-tag">      <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;stylesheet&quot;</span></span><br><span class="hljs-tag">    /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br>  <br>  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>           ................................<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://fontawesome.com/v4/icon/battery-full">fa-battery-full: Font Awesome Icons</a></p>
<p><a target="_blank" rel="noopener" href="https://www.runoob.com/font-awesome/fontawesome-tutorial.html">Font Awesome 图标 | 菜鸟教程</a></p>
<p><a target="_blank" rel="noopener" href="https://www.runoob.com/jquery/jquery-install.html">jQuery 安装 | 菜鸟教程</a></p>
<p><img src="http://blog.memory-life.xyz/image-20250923231416752.png" alt="image-20250923231416752"></p>
<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><blockquote>
<p>2025 年 1 月 15 日</p>
</blockquote>
<p>入职一个月以来，每天在整理工作笔记之余，也会抽时间发散思维，记录灵感，去探索一些新的东西。</p>
<p>这个栏目开设在去年夏天，原本计划用来记录拉取学习并系统梳理的新项目，有效扩充技术广度。</p>
<p>这样的想法和行动于我而言很有吸引力，不过在后半年由于就业环境的冲击以及秋招带来的无形压力，国庆以后便被迫短暂搁置了。</p>
<p>从今天开始，我会尝试在这个栏目下持续记录自己的思考过程。</p>
<p>我的编程之旅，或许这个栏目才是其真正的精神续作吧。</p>
<p>最近也会有很多新的想法和开发思路，所有笔记逐步从泰豪实习工作栏目下迁移到这里，并稍作整理了一番。</p>

                
              </div>
            
            <hr/>
            <div>
              <!-- 文章页面 - 底部标签 -->
<div class="post-metas my-3">
  
  <div class="post-meta mr-3 d-flex align-items-center">
    <i class="iconfont icon-category"></i>
    <!-- 归档页 - 文章列表 -->


<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/blog/categories/%E4%BB%A3%E7%A0%81%E9%94%8B%E8%8A%92/" class="category-chain-item">代码锋芒</a>
  
  

      </span>
    
  
</span>

  </div>
   
  <div class="post-meta">
    <i class="iconfont icon-tags"></i>
    
    <a href="/blog/tags/%E9%A1%B9%E7%9B%AE/">#项目</a>
    
    <a href="/blog/tags/Vue/">#Vue</a>
    
    <a href="/blog/tags/%E6%AF%95%E8%AE%BE/">#毕设</a>
    
  </div>
  
</div>


              <!-- 文章页面 - 底部标签下方 -->

  
  <div class="license-box my-3">
    <div class="license-title">
      <div>卓越之旅：在优秀案例中精进，编织技术梦想</div>
      <div>https://test.atomgit.net/blog/2024/07/12/卓越之旅：在优秀案例中精进，编织技术梦想/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>Memory</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2024年7月12日</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>更新于</div>
          <div>2025年11月7日</div>
        </div>
      
      
        <div class="license-meta-item">
          <div>许可协议</div>
          <div>
            
              
              
                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>
              
            
          </div>
        </div>
      
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/blog/2024/07/14/%E6%82%A0%E7%84%B6%E6%97%A5%E5%B8%B8%EF%BC%9A%E6%85%A2%E7%85%AE%E6%97%B6%E5%85%89%E4%B8%8B%E7%9A%84%E7%94%9F%E6%B4%BB%E8%89%BA%E6%9C%AF/" title="悠然日常：慢煮时光下的生活艺术">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">悠然日常：慢煮时光下的生活艺术</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/blog/2024/07/12/%E5%8C%A0%E5%BF%83%E7%8B%AC%E8%BF%90%EF%BC%9A%E6%8E%A2%E7%B4%A2%E8%A7%86%E9%A2%91%E5%88%9B%E4%BD%9C%E7%9A%84%E8%89%BA%E6%9C%AF%E6%B7%B1%E5%BA%A6%E4%B8%8E%E5%B9%BF%E5%BA%A6/" title="匠心独运：探索视频创作的艺术深度与广度">
                        <span class="hidden-mobile">匠心独运：探索视频创作的艺术深度与广度</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            <!-- 文章页 - 评论上方 -->

  
  
    <article id="comments">
      
  <div id="valine"></div>
  <script type="text/javascript">
    Fluid.utils.loadComments('#valine', function() {
      Fluid.utils.createScript('https://cdn.jsdelivr.net/gh/HCLonely/Valine@latest/dist/Valine.min.js', function() {
        var options = Object.assign(
          {"appId":"T1hUHH9Ks1ggG9DBE3HgUPpV-gzGzoHsz","appKey":"XFkgzzvzNo3J3uNCbBiSOFKc","path":"window.location.pathname","placeholder":"填取QQ号和邮箱后评论，支持读取头像及消息提醒，留下点什么叭... ᶘ ᵒᴥᵒᶅ","avatar":"Gravatar","meta":["nick","mail","link"],"requiredFields":[],"pageSize":10,"lang":"zh-CN","highlight":true,"recordIP":false,"serverURLs":"https://t1huhh9k.lc-cn-n1-shared.com","emojiCDN":null,"emojiMaps":null,"enableQQ":true,"master":"8c9b6d6637904da62d74d019cc6982de","friends":"0188229a9cfc284176ea9135cb9514cc","visitor":true},
          {
            el: "#valine",
            path: window.location.pathname,
            app_id: "",
            app_key: "",
            placeholder: "填取QQ号和邮箱后评论，支持读取头像及消息提醒，留下点什么叭... ᶘ ᵒᴥᵒᶅ",
            avatar: "Gravatar",
            meta: ["nick","mail","link"],
            pageSize: "10",
            lang: "zh-CN",
            highlight: true,
            recordIP: false,
            serverURLs: "https://t1huhh9k.lc-cn-n1-shared.com",

            // 设置Bilibili表情包地址
            emojiCDN: '//i0.hdslb.com/bfs/emote/', 
            // 表情title和图片映射
            emojiMaps: {
                "tv_白眼": "48f75163437445665a9be80bb316e4cb252c5415.gif@48w_48h.webp",
                "tv_doge": "302d6c88c63ed162c81a49cafe7ed2709e6fb955.gif@48w_48h.webp",
                "tv_坏笑": "5d2572efd09aab5dde9e2a198bb3f9ac1e2a982e.gif@48w_48h.webp",
                "tv_难过": "9c6b41008a67755410f712334c64313df5f91b3f.gif@48w_48h.webp",
                "tv_生气": "1902a5a2df5b5c931d88c12f0feb264b1e109d0d.gif@48w_48h.webp",
                "tv_委屈": "af5a5853edb43a8178a8cb5df707fa5e88143699.gif@48w_48h.webp",
                "tv_斜眼笑": "c66568b471192ca1f62f6ed4384dc1b283ab7508.gif@48w_48h.webp",
                "tv_呆": "d3fa91e4db9215eb1e20ab9da44f1214aa4bda7b.gif@48w_48h.webp",
                "tv_发怒": "3959eb81b952e4fa8d269d98f9e3639172d84073.gif@48w_48h.webp",
                "tv_呕吐": "db58e9442aae26694af18cc1683607cca3a16763.gif@48w_48h.webp",
                "tv_思考": "b63f9146bfd985af014f8d6d4bdb498805be48f9.gif@48w_48h.webp",
                "tv_微笑": "b98656855d782f61cb8edc7f7fca6563ecafff7e.gif@48w_48h.webp",
                "tv_疑问": "fce1b1a0f3b0e39a2dc16a18508dba7b91e929f4.gif@48w_48h.webp",
                "tv_大哭": "cba61f05f3039b02a7ffc0dfcd9d7995df9fdd74.gif@48w_48h.webp",
                "tv_鼓掌": "be106e6b265883a9f28fbe10f7b765701e2618d4.gif@48w_48h.webp",
                "tv_抠鼻": "696d9f93e722144dc2a78aeffc569418fdf3d565.gif@48w_48h.webp",
                "tv_亲亲": "3534ea44ab74bd20352b88c245a06c4b4c46d271.gif@48w_48h.webp",
                "tv_调皮": "fcd967395fd14e4dd5829fa7e8a967ce23205e52.gif@48w_48h.webp",
                "tv_笑哭": "1c2fd1e8c9dde12812f86e5d4cbddd8993d98082.gif@48w_48h.webp",
                "tv_晕": "030040ec5c9ddc9e3d067658c4139e7314ab42f8.gif@48w_48h.webp",
                "tv_点赞": "30ecff401245fb56bcc1cf588d1809ac1ab1607c.gif@48w_48h.webp",
                "tv_害羞": "411a3e459e8580f5bfd9f639a408247c4b509935.gif@48w_48h.webp",
                "tv_睡着": "3c8b5e293261287a6203597e29b3de07df4d18c6.gif@48w_48h.webp",
                "tv_色": "a0c6d99ab0ab63b8648f5283ff72cec04b604828.gif@48w_48h.webp",
                "tv_吐血": "e17e4539e169d14a3389ff147afea760cebe5de5.gif@48w_48h.webp",
                "tv_无奈": "eb4cb5f07cfd177c7e6a7914316717e56d9cc1d0.gif@48w_48h.webp",
                "tv_再见": "344f61609ecce2008520dc8a977b6169215748a9.gif@48w_48h.webp",
                "tv_流汗": "390bccec65eaff536bd5bb2a0c5b8b0bdea47334.gif@48w_48h.webp",
                "tv_偷笑": "7f11e6f7f63e79112b833bd41fa13a83d7cd8474.gif@48w_48h.webp",
                "tv_抓狂":"a476b93ecd8e94ac3257323fd822f91cef212de2.gif@48w_48h.webp",
                "tv_黑人问号":"b609adf664be33224a9923262031165ae3e34cd2.gif@48w_48h.webp",
                "tv_困":"91c2bf34ecf842d7016c01d841db3d4074bd281f.gif@48w_48h.webp",
                "tv_打脸":"b0fad4856e59c1240e448437da3287bb5ce547e5.gif@48w_48h.webp",
                "tv_闭嘴":"a3fc5388b09e945be3f18fe23bfed5874a0285b7.gif@48w_48h.webp",
                "tv_鄙视":"293b5d459e6264ecf314d20937a936fa672ccd1e.gif@48w_48h.webp",
                "tv_腼腆":"30984e8264324f901d19bea85dada7103b695534.gif@48w_48h.webp",
                "tv_馋":"2525c5703c594e5f0752f68db8948773caebde47.gif@48w_48h.webp",
                "tv_可爱":"f92d20f76258bc5f33fc9d7c5e2a1d41fef19a7c.gif@48w_48h.webp",
                "tv_发财":"76131e52c9b033681b4c896c6024d29ef7ec7ec2.gif@48w_48h.webp",
                "tv_生病":"beb94829fe04f1a41bd6ca611e1f6ca9ca169afa.gif@48w_48h.webp",
                "tv_流鼻血":"8ef473f74a849420da712487b2f56ecca1f695f5.gif@48w_48h.webp",
                "tv_尴尬":"e0b84ef5ee3e5b8978e584c7c5a6550c51d15f84.gif@48w_48h.webp",
                "tv_大佬":"14ca0c05382b8741940942b2430b7a8d55c02f7e.gif@48w_48h.webp",
                "tv_流泪":"7e71cde7858f0cd50d74b0264aa26db612a8a167.png@48w_48h.webp",
                "tv_冷漠":"b9cbc755c2b3ee43be07ca13de84e5b699a3f101.png@48w_48h.webp",
                "tv_皱眉":"72ccad6679fea0d14cce648b4d818e09b8ffea2d.png@48w_48h.webp",
                "tv_鬼脸":"0ffbbddf8a94d124ca2f54b360bbc04feb6bbfea.png@48w_48h.webp",
                "tv_调侃":"4bc022533ef31544ca0d72c12c808cf4a1cce3e3.png@48w_48h.webp",
                "tv_目瞪口呆":"0b8cb81a68de5d5365212c99375e7ace3e7891b7.png@48w_48h.webp",
            },

            master: "8c9b6d6637904da62d74d019cc6982de",
            friends: "0188229a9cfc284176ea9135cb9514cc",
            tagMeta: ["博主","友人","访客"],
            visitor: true // 阅读量统计
          }
        )
        new Valine(options);
        Fluid.utils.waitElementVisible('#valine .vcontent', () => {
          var imgSelector = '#valine .vcontent img:not(.vemoji)';
          Fluid.plugins.imageCaption(imgSelector);
          Fluid.plugins.fancyBox(imgSelector);
        })
      });
    });
  </script>
  <noscript>Please enable JavaScript to view the comments</noscript>


    </article>
  


          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      <!-- 文章页面 - 右侧目录 -->

  <aside class="sidebar" style="margin-left: -1rem">
    <!-- 文章页面 - 右侧目录上方 -->
<div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>



    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <!-- 博客 - 搜索框 -->
<div
  class="modal fade"
  id="modalSearch"
  tabindex="-1"
  role="dialog"
  aria-labelledby="ModalLabel"
  aria-hidden="true"
>
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">
          搜索
        </h4>
        <button
          type="button"
          id="local-search-close"
          class="close"
          data-dismiss="modal"
          aria-label="Close"
        >
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input
            type="text"
            id="local-search-input"
            class="form-control validate"
          />
          <label data-error="x" data-success="v" for="local-search-input"
            >关键词</label
          >
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
        <div class="modal fade" id="modalNotice" tabindex="-1" role="dialog" aria-hidden="true"
     style="font-family: 'Ma Shan Zheng', cursive; color: #ffffff;">
    <div class="modal-dialog modal-dialog-scrollable" role="document"
         style="font-family: 'Ma Shan Zheng', cursive;">
        <div class="modal-content" style="border-radius: 6px;">
            <!-- 公告头部 - 响应式设计 -->
            <div class="modal-header text-center"
                 style="padding: 1rem 1.5rem;border-bottom: 1px solid rgba(255,255,255,0.2)">
                <h4 class="modal-title w-100 font-weight-bold"
                    style="font-family: 'Microsoft YaHei', sans-serif;letter-spacing: 1px;text-shadow: 1px 1px 2px rgba(0,0,0,0.2);color: #ffffff;
                           font-size: 1.5rem; /* 默认PC端大小 */
                           /* 移动端适配 */
                           @media (max-width: 768px) {
                               font-size: 1.2rem;
                           }">
                    <div class="notice-title">
                        <i class="fas fa-bullhorn mr-2"> 围栏告示</i>
                    </div>
                    <small style="display: block; font-family: 'STKaiti', serif; font-size: 0.6em; color: #a0a0a0; margin-top: 3px;">
                        旧梦轻拾 · 谨识
                    </small>
                </h4>
            </div>

            <!-- 公告内容区 - 响应式设计 -->
            <div class="modal-body"
                 style="padding: 2rem; /* PC端 */
                        max-height: 70vh;
                        overflow-y: auto;
                        /* 移动端适配 */
                        @media (max-width: 768px) {
                            padding: 1rem;
                            max-height: 60vh;
                        }">
                <!-- 图片容器（响应式设计） -->
                <!--                <div class="announcement-hero"-->
                <!--                     style="margin-bottom: 2rem; /* PC端 */-->
                <!--                            /* 移动端适配 */-->
                <!--                            @media (max-width: 768px) {-->
                <!--                                margin-bottom: 1rem;-->
                <!--                            }">-->
                <!--                    <img src="http://blog.memory-life.icu/%E3%80%90%E5%93%B2%E9%A3%8E%E5%A3%81%E7%BA%B8%E3%80%91%E5%8A%A8%E6%BC%AB-%E5%A4%95%E9%98%B3%E9%93%81%E8%BD%A8.jpg"-->
                <!--                         alt="时光溯洄题图"-->
                <!--                         style="width: 100%; -->
                <!--                                max-height: 400px; /* PC端 */-->
                <!--                                object-fit: cover;-->
                <!--                                border-radius: 4px; -->
                <!--                                box-shadow: 0 2px 12px rgba(0,0,0,0.1);-->
                <!--                                /* 移动端适配 */-->
                <!--                                @media (max-width: 768px) {-->
                <!--                                    max-height: 30vh;-->
                <!--                                }"-->
                <!--                         loading="lazy">-->
                <!--                </div>-->

                <!-- 静态公告列表 - 响应式设计 -->
                <div class="announcement-list">
                    <div class="announcement-item"
                         style="margin-bottom: 2rem; /* PC端 */
                                padding: 2rem;
                                background: rgba(255,255,255,0.05);
                                border-radius: 8px;
                                /* 移动端适配 */
                                @media (max-width: 768px) {
                                    margin-bottom: 1rem;
                                    padding: 1rem;
                                }">
                        <h2 style="color: #d38532;
                                  font-weight: 600;
                                  font-size: 1.5rem; /* PC端 */
                                  margin-bottom: 1.2rem;
                                  letter-spacing: 0.5px;
                                  /* 移动端适配 */
                                  @media (max-width: 768px) {
                                      font-size: 1.2rem;
                                      margin-bottom: 1rem;
                                  }">
                            <i class="fas fa-calendar-check mr-2"></i>时光溯洄
                            <small style="display: block; font-size: 0.6em; color: #b8b8b8;text-align: right;">——
                                晨昏往事</small>
                        </h2>
                        <div style="color: #e0e0e0;
                                  line-height: 1.8; /* PC端 */
                                  font-size: 1.05rem;
                                  letter-spacing: 0.3px;
                                  /* 移动端适配 */
                                  @media (max-width: 768px) {
                                      line-height: 1.6;
                                      font-size: 0.95rem;
                                  }">
                            <!-- 内容保持不变 -->
                            <p style="margin-bottom: 1rem; text-indent: 2em;">你好。</p>
                            <!-- 其余段落内容... -->
                            <p style="margin-bottom: 1rem; text-indent: 2em;">
                                建站后的第813天，在百忙之中总算又能抽出时间来，对整个博客站点功能做整体的规划及优化完善。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em;">
                                在刚刚过去的几年时间里，往事皆以笔墨挥毫于时光素笺之上，数百天如一日，故事的书写从未间断过。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em; font-style: italic; color: #b8b8b8;">
                                时光悠悠，日月如流，过往的蹉跎岁月总在不经意间在心间回眸。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em; font-weight: 500; color: #ffffff;">
                                俯仰之间，轻舟已过万重山。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em; font-weight: 500; color: #ffffff;">
                                蹉跎之处，往事皆成云烟散。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em;">
                                这几年的时光过得太快了，好像过去这段岁月里的所有事情都发生在一瞬间。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em;">
                                这几年的时光同样太久了，久到那些时日里仿佛囊括了自己的整个前半生。</p>
                            <p style="margin-bottom: 0; text-align: right; font-size: 0.95rem; color: #a0a0a0;">——
                                八百余个昼夜，当时只道是地久天长，如今回望，不过浮光掠影间的一瞬。</p>
                        </div>
                    </div>

                    <!-- 第二个公告项 - 响应式设计 -->
                    <div class="announcement-item"
                         style="margin-bottom: 2rem; /* PC端 */
                                padding: 2rem;
                                background: rgba(255,255,255,0.05);
                                border-radius: 8px;
                                /* 移动端适配 */
                                @media (max-width: 768px) {
                                    margin-bottom: 1rem;
                                    padding: 1rem;
                                }">
                        <h2 style="color: #6cc70b;
                                  font-weight: 600;
                                  font-size: 1.5rem; /* PC端 */
                                  margin-bottom: 1.2rem;
                                  letter-spacing: 0.5px;
                                  /* 移动端适配 */
                                  @media (max-width: 768px) {
                                      font-size: 1.2rem;
                                      margin-bottom: 1rem;
                                  }">
                            <i class="fas fa-book-open mr-2"></i>墨痕新注
                            <small style="display: block; font-size: 0.6em; color: #b8b8b8;text-align: right;">——
                                待起之章</small>
                        </h2>
                        <div style="color: #e0e0e0;
                                  line-height: 1.8; /* PC端 */
                                  font-size: 1.05rem;
                                  letter-spacing: 0.3px;
                                  /* 移动端适配 */
                                  @media (max-width: 768px) {
                                      line-height: 1.6;
                                      font-size: 0.95rem;
                                  }">
                            <!-- 列表内容 - 响应式设计 -->
                            <ul style="padding-left: 1.8rem; /* PC端 */
                                      margin-bottom: 1.5rem;
                                      /* 移动端适配 */
                                      @media (max-width: 768px) {
                                          padding-left: 1.5rem;
                                          margin-bottom: 1.2rem;
                                      }">
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">溯源计划：</span>新增博文"溯源计划"，旨在用先进的数字技术留住过去的旧时光，让家族的记忆在数字云端生长发芽，全站博文数量已达90+。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">围栏告示：</span>自去年夏天站点新增了“评论回复”功能后，至今时隔十余月，在芒种前夕本站久违地上线“围栏告示”功能，本公告栏会不定时更新，持续跟进记录最新站点功能调整日志，更多精彩内容请敬请期待。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">图片查看：</span>最近几周时间里，考虑到图文流量费用收取问题，暂时关闭了七牛云对象存储私有空间访问权限，故博文内的图文无法正常预览，择日考虑开启访问权限。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">壁纸下载：</span>后续计划实现壁纸下载功能，均为个人收集的共150+超高分辨率精美壁纸，提供在线预览以及下载功能。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">阅读体验：</span>规划完善文章内分页功能，并提供“最近更新”的文章列表，计划收录更新率较高的文章，譬如：阳台日记、叙事之外、岁月如歌、游戏人生等等，尽可能多的提升在线浏览和阅读体验。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">友链完善：</span>持续优化完善友链页面，整理归档个人常用的高质量网站合集，无偿分享给有缘人。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">音乐餐厅：</span>历经十余小时不间断调研和尝试，本站成功上线”音乐餐厅”功能，目前仅收录了个人在QQ音乐平台积累的两份歌单，再匆忙也要记得点播一首喜欢的音乐，没有音乐熏陶的心灵终究是充满缺憾的。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">三言两语：</span>每张照片都是时光的便签，随手一贴就记下了那天，本站结合Mamos实现并注入留言板功能，随缘记录那些藏在照片背后的故事。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">旧梦轻拾：</span>更新全站博客文章所属分类，共设有代码锋芒、部署之道、旧梦轻拾、人间片刻等十余种分类。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">方寸之间：</span>博客应用版发布，更便捷的阅读体验来了！现已正式推出独立的桌面应用程序与移动端应用程序，暂时通过网盘和代码库提供安装包。
                                </li>
                                <p style="margin-bottom: 0; text-align: right; font-size: 0.9rem; color: #8a8a8a;">
                                    此公告最后更新于：<span style="color: #6cc70b;">2025/09/30晚</span>
                                </p>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 公告页脚 - 响应式设计 -->
            <div class="modal-footer"
                 style="border-top: 1px solid rgba(255,255,255,0.2);
                        padding: 1rem 1.5rem; /* PC端 */
                        justify-content: space-between;
                        /* 移动端适配 */
                        @media (max-width: 768px) {
                            padding: 0.8rem;
                        }">
                <small style="color: #ffffff;
                            font-size: 0.9rem; /* PC端 */
                            /* 移动端适配 */
                            @media (max-width: 768px) {
                                font-size: 0.8rem;
                            }">
                    <i class="iconfont icon-pen"></i>
                    <i class="fas fa-info-circle mr-1"></i>芒种前夕 · 旅途第813天
                    · 2025/05/28
                </small>
                <button id="confirm-btn" type="button" class="btn btn-sm" data-dismiss="modal"
                        style="background: #a0a0a0;
                               color: #ffffff;
                               border-radius: 4px;
                               padding: 0.5rem 1.2rem; /* PC端 */
                               border: none;
                               font-size: 0.9rem;
                               /* 移动端适配 */
                               @media (max-width: 768px) {
                                   padding: 0.3rem 0.8rem;
                                   font-size: 0.85rem;
                               }">
                    <i class="fas fa-check mr-1" style="color: #ffffff;">心已阅</i>
                </button>
            </div>
        </div>
    </div>
</div>

<style>
  .notice-title {
    display: flex;
    align-items: center;
    white-space: nowrap;
  }

  .notice-title:before,
  .notice-title:after {
    content: "";
    flex: 1;
    height: 1px;
    background: #ddd; /* 横线颜色 */
    margin: 0 10px; /* 横线与文字的间距 */
  }
</style>


<style>
  /* 响应式模态框宽度 */
  @media (min-width: 992px) {
    #modalNotice .modal-dialog {
      max-width: 800px;
    }
  }

  @media (max-width: 991px) {
    #modalNotice .modal-dialog {
      margin: 0.5rem auto;
    }
  }
</style>

<script>
  // 页面加载完成后执行
  document.addEventListener('DOMContentLoaded', function () {
    // 检查是否首次访问
    if (!localStorage.getItem('hasShownPopup')) {
      // 动态加载notice.ejs内容
      fetch('_partials/notice.ejs')  // 替换为实际路径
        .then(response => response.text())
        .then(html => {
          // 插入到页面body末尾
          document.body.insertAdjacentHTML('beforeend', html);

          // 手动初始化Bootstrap模态框
          $('#modalNotice').modal('show');

          // 标记为已显示
          localStorage.setItem('hasShownPopup', 'true');

          // 监听关闭事件
          $('#modalNotice').on('hidden.bs.modal', function () {
            // 可选的后续处理
          });
        })
        .catch(error => {
          console.error('加载公告栏失败:', error);
          // 备用方案：显示简单弹窗
          const fallbackHTML = `
                <div class="modal-backdrop" style="/* 样式 */">
                    <div class="modal-content">/* 内容 */</div>
                </div>`;
          document.body.insertAdjacentHTML('beforeend', fallbackHTML);
        });
    }
  });
</script>

    

    
  </main>

  <footer>
    <!-- 博客 - 页脚 -->
<div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.fluid-dev.com/docs/guide/" target="_blank" rel="nofollow noopener"> <span>Memory | 个人文档站点</span> </a>
<i class="iconfont icon-love"></i> <a href="https://hexo.fluid-dev.com/docs/guide/" target="_blank" rel="nofollow noopener"> <span>配置指南 | Hexo Fluid 用户手册</span> </a> 
    </div>
  

  

  
    <!-- 备案信 ICP for China -->
    <div class="beian">
  <span>
    <a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">
      京ICP证123456号
    </a>
  </span>
  
    
      <span>
        <a
          href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=12345678"
          rel="nofollow noopener"
          class="beian-police"
          target="_blank"
        >
          
            <span style="visibility: hidden; width: 0">|</span>
            <img src="/blog/img/police_beian.png" alt="police-icon"/>
          
          <span>京公网安备12345678号</span>
        </a>
      </span>
    
  
</div>

  

  

</div>

<!-- 评论框美化 -->
<style>
    #comments .veditor{
        min-height: 20vh;
        background-image: url(http://blog.memory-life.icu/pathway0716.jpg);
        background-size: contain;
        background-repeat: no-repeat;
        background-position: right;
        background-color: rgba(255,255,255,0);
        resize: none;}
</style>

<script>
    //   自定义邮箱审核规则
    document.body.addEventListener('click', function(e) {
        if (e.target.classList.contains('vsubmit')) {
            const email = document.querySelector('input[type=email]');
            const nick = document.querySelector('input[name=nick]');
            const reg = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
            if (!email.value || !nick.value || !reg.test(email.value)) {
                const str = `<div class="valert text-center"><div class="vtext">请填写正确的昵称和邮箱！</div></div>`;
                const vmark = document.querySelector('.vmark');
                vmark.innerHTML = str;
                vmark.style.display = 'block';
                setTimeout(function() {
                    vmark.style.display = 'none';
                    vmark.innerHTML = '';
                }, 2500);
            }
        }
    })
</script>



  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/blog/js/events.js" ></script>
<script  src="/blog/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>







  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.11/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/blog/js/local-search.js" ></script>

  <script defer src="/blog/js/leancloud.js" ></script>




    
<script src="https://cdn.jsdelivr.net/npm/aplayer@1.10.1/dist/APlayer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>



<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/blog/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
